/* test.c
 *
 * Copyright (C) 2006-2013 wolfSSL Inc.
 *
 * This file is part of CyaSSL.
 *
 * CyaSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * CyaSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
//#define NO_DH
//#define NO_PWDBASED
#ifdef HAVE_CONFIG_H
    #include "config.h"
#endif





#include "cyassl/ctaocrypt/settings.h"

#ifdef CYASSL_TEST_CERT
    #include "cyassl/ctaocrypt/asn.h"
#else
    #include "cyassl/ctaocrypt/asn_public.h"
#endif
#include "cyassl/ctaocrypt/md2.h"
#include "cyassl/ctaocrypt/md5.h"
#include "cyassl/ctaocrypt/md4.h"
#include "cyassl/ctaocrypt/sha.h"
#include "cyassl/ctaocrypt/sha256.h"
#include "cyassl/ctaocrypt/sha512.h"
#include "cyassl/ctaocrypt/arc4.h"
#include "cyassl/ctaocrypt/random.h"
#include "cyassl/ctaocrypt/coding.h"
#include "cyassl/ctaocrypt/rsa.h"
#include "cyassl/ctaocrypt/des3.h"
#include "cyassl/ctaocrypt/aes.h"
#include "cyassl/ctaocrypt/camellia.h"
#include "cyassl/ctaocrypt/hmac.h"
#include "cyassl/ctaocrypt/dh.h"
#include "cyassl/ctaocrypt/dsa.h"
#include "cyassl/ctaocrypt/hc128.h"
#include "cyassl/ctaocrypt/rabbit.h"
#include "cyassl/ctaocrypt/pwdbased.h"
#include "cyassl/ctaocrypt/ripemd.h"
#include "print_funcs.h"
#include "printf-stdarg.h"

#ifdef HAVE_ECC
    #include "cyassl/ctaocrypt/ecc.h"
#endif    
#ifdef HAVE_BLAKE2
    #include "cyassl/ctaocrypt/blake2.h"
#endif    
#ifdef HAVE_LIBZ
    #include "cyassl/ctaocrypt/compress.h"
#endif

#ifdef _MSC_VER
    /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
    #pragma warning(disable: 4996)
#endif

#ifdef OPENSSL_EXTRA
    #include "cyassl/openssl/evp.h"
    #include "cyassl/openssl/rand.h"
    #include "cyassl/openssl/hmac.h"
    #include "cyassl/openssl/des.h"
#endif

#if defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048)
    /* include test cert and key buffers for use with NO_FILESYSTEM */
    #include "cyassl/certs_test.h"
#endif

#ifdef HAVE_NTRU
    #include "crypto_ntru.h"
#endif
#ifdef HAVE_CAVIUM
    #include "cavium_sysdep.h"
    #include "cavium_common.h"
    #include "cavium_ioctl.h"
#endif

#include "string.h"
#ifdef FREESCALE_MQX
    #include "mqx.h"
    #include "fio.h"
#else
    #include "stdio.h"
#endif
#include "stdlib.h"


#ifdef THREADX
    /* since just testing, use THREADX log print_dbg instead */
    int dc_log_printf(char*, ...);
        #undef printf
        #define printf dc_log_printf
#endif

#include "ctaocrypt/test/test.h"
//#include "cyassl/test.h"

///aaaaaaaaaa    start

















#ifdef BENCHMARK

#include "tc_1.h"


//
//
//
//#include <stdint.h>
//#include <stdbool.h>
////
////#include "sysclk.h"   ----> #include "tc_1.h"
//
//
//
//
//
//
//
//#include "board.h"
//#include "print_funcs.h"
//#include "tc.h"
//#include "gpio.h"
//#if defined (__GNUC__)
//#  include "intc.h"
//#endif
//#include "conf_example.h"
//
//
//
//
////! \name Example configuration
////!@{
///**
 //* \def CONFIG_SYSCLK_SOURCE
 //* \brief Clock source to use
 //*/
///**
 //* \def EXAMPLE_TC
 //* \brief Base address of TC module to use.
 //*/
///**
 //* \def EXAMPLE_TC_CHANNEL
 //* \brief Channel to use with TC module.
 //*/
///**
 //* \def EXAMPLE_TC_IRQ
 //* \brief IRQ Line number for TC module
 //*/
 ///**
 //* \def EXAMPLE_TC_IRQ_PRIORITY
 //* \brief IRQ Group number for TC module
 //*/
////!@}
//
//// Flag to update the timer value
//volatile static bool update_timer = true;
//// Variable to contain the time ticks occurred
//volatile static uint32_t tc_tick = 0;
//
//
///**
 //* \brief TC interrupt.
 //*
 //* The ISR handles RC compare interrupt and sets the update_timer flag to
 //* update the timer value.
 //*/
//#if defined (__GNUC__)
//__attribute__((__interrupt__))
//#elif defined (__ICCAVR32__)
//#pragma handler = EXAMPLE_TC_IRQ_GROUP, 1
//__interrupt
//#endif
//static void tc_irq(void)
//{
	//// Increment the ms seconds counter
	//tc_tick++;
//
	//// Clear the interrupt flag. This is a side effect of reading the TC SR.
	//tc_read_sr(EXAMPLE_TC, EXAMPLE_TC_CHANNEL);
//
	//// specify that an interrupt has been raised
	//update_timer = true;
	//// Toggle a GPIO pin (this pin is used as a regular GPIO pin).
	//LED_Toggle(LED0);
//}
//
///**
 //* \brief TC Initialization
 //*
 //* Initializes and start the TC module with the following:
 //* - Counter in Up mode with automatic reset on RC compare match.
 //* - fPBA/8 is used as clock source for TC
 //* - Enables RC compare match interrupt
 //* \param tc Base address of the TC module
 //*/
//static void tc_init(volatile avr32_tc_t *tc)
//{
	//// Options for waveform generation.
	//static const tc_waveform_opt_t waveform_opt = {
		//// Channel selection.
		//.channel  = EXAMPLE_TC_CHANNEL,
		//// Software trigger effect on TIOB.
		//.bswtrg   = TC_EVT_EFFECT_NOOP,
		//// External event effect on TIOB.
		//.beevt    = TC_EVT_EFFECT_NOOP,
		//// RC compare effect on TIOB.
		//.bcpc     = TC_EVT_EFFECT_NOOP,
		//// RB compare effect on TIOB.
		//.bcpb     = TC_EVT_EFFECT_NOOP,
		//// Software trigger effect on TIOA.
		//.aswtrg   = TC_EVT_EFFECT_NOOP,
		//// External event effect on TIOA.
		//.aeevt    = TC_EVT_EFFECT_NOOP,
		//// RC compare effect on TIOA.
		//.acpc     = TC_EVT_EFFECT_NOOP,
		///*
		 //* RA compare effect on TIOA.
		 //* (other possibilities are none, set and clear).
		 //*/
		//.acpa     = TC_EVT_EFFECT_NOOP,
		///*
		 //* Waveform selection: Up mode with automatic trigger(reset)
		 //* on RC compare.
		 //*/
		//.wavsel   = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,
		//// External event trigger enable.
		//.enetrg   = false,
		//// External event selection.
		//.eevt     = 0,
		//// External event edge selection.
		//.eevtedg  = TC_SEL_NO_EDGE,
		//// Counter disable when RC compare.
		//.cpcdis   = false,
		//// Counter clock stopped with RC compare.
		//.cpcstop  = false,
		//// Burst signal selection.
		//.burst    = false,
		//// Clock inversion.
		//.clki     = false,
		//// Internal source clock 3, connected to fPBA / 8.
		//.tcclks   = TC_CLOCK_SOURCE_TC3
	//};
//
	//// Options for enabling TC interrupts
	//static const tc_interrupt_t tc_interrupt = {
		//.etrgs = 0,
		//.ldrbs = 0,
		//.ldras = 0,
		//.cpcs  = 1, // Enable interrupt on RC compare alone
		//.cpbs  = 0,
		//.cpas  = 0,
		//.lovrs = 0,
		//.covfs = 0
	//};
	//// Initialize the timer/counter.
	//tc_init_waveform(tc, &waveform_opt);
//
	///*
	 //* Set the compare triggers.
	 //* We configure it to count every 1 milliseconds.
	 //* We want: (1 / (fPBA / 8)) * RC = 1 ms, hence RC = (fPBA / 8) / 1000
	 //* to get an interrupt every 10 ms.
	 //*/
	//tc_write_rc(tc, EXAMPLE_TC_CHANNEL, (sysclk_get_pba_hz() / 8 / 1000));
	//// configure the timer interrupt
	//tc_configure_interrupts(tc, EXAMPLE_TC_CHANNEL, &tc_interrupt);
	//// Start the timer/counter.
	//tc_start(tc, EXAMPLE_TC_CHANNEL);
//}
//
///*! \brief Main function:
 //*  - Configure the CPU to run at 12MHz
 //*  - Configure the USART
 //*  - Register the TC interrupt (GCC only)
 //*  - Configure, enable the CPCS (RC compare match) interrupt, and start a
 //*    TC channel in waveform mode
 //*  - In an infinite loop, update the USART message every second.
 //*/
//


















#endif




//aaaaaaaaaaaaaa  end
typedef struct testVector {
    const char*  input;
    const char*  output; 
    size_t inLen;
    size_t outLen;
} testVector;

int  md2_test(void);
int  md5_test(void);
int  md4_test(void);
int  sha_test(void);
int  sha256_test(void);
int  sha512_test(void);
int  sha384_test(void);
int  hmac_md5_test(void);
int  hmac_sha_test(void);
int  hmac_sha256_test(void);
int  hmac_sha384_test(void);
int  hmac_sha512_test(void);
int  arc4_test(void);
int  hc128_test(void);
int  rabbit_test(void);
int  des_test(void);
int  des3_test(void);
int  aes_test(void);
int  aesgcm_test(void);
int  aesccm_test(void);
int  camellia_test(void);
int  rsa_test(void);
int  dh_test(void);
int  dsa_test(void);
int  random_test(void);
int  pwdbased_test(void);
int  ripemd_test(void);
int  openssl_test(void);   /* test mini api */
int pbkdf1_test(void);
int pkcs12_test(void);
int pbkdf2_test(void);
#ifdef HAVE_ECC
    int  ecc_test(void);
#endif
#ifdef HAVE_BLAKE2
    int  blake2b_test(void);
#endif
#ifdef HAVE_LIBZ
    int compress_test(void);
#endif


#ifdef BENCHMARK
	//double current_time(void);
   
   void bench_des(void);
   void bench_arc4(void);
   void bench_hc128(void);
   void bench_rabbit(void);
   void bench_aes(int);
   void bench_aesgcm(void);
   void bench_aesccm(void);
   void bench_camellia(void);

   void bench_md5(void);
   void bench_sha(void);
   void bench_sha256(void);
   void bench_sha512(void);
   void bench_ripemd(void);

   void bench_rsa(void);
   void bench_rsaKeyGen(void);
   void bench_dh(void);
   #ifdef HAVE_ECC
   void bench_eccKeyGen(void);
   void bench_eccKeyAgree(void);
   #endif




#ifdef BENCH_EMBEDDED
const int numBlocks = 25;       /* how many kB/megs to test (en/de)cryption */
const char blockType[] = "kB";  /* used in printf output */
const int times     = 1;        /* public key iterations */
#else
const int numBlocks = 5;
const char blockType[] = "megs";
const int times     = 100;
#endif








const byte key[] =
{
    0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
    0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10,
    0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
};

const byte iv[] =
{
    0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef,
    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
    0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81

};










/* use kB instead of mB for embedded benchmarking */
#ifdef BENCH_EMBEDDED
byte plain [1024];
byte cipher[1024];
#else
byte plain [1024*1024];
byte cipher[1024*1024];
#endif

#endif

static void err_sys(const char* msg, int es)
{
    printf("%s error = %d\r\r\n", msg, es);
#ifndef THREADX
    if (msg)
        exit(es);
#endif
    return;
}

///* func_args from test.h, so don't have to pull in other junk */
//typedef struct func_args {
//    int    argc;
//    char** argv;
//    int    return_code;
//} func_args;








void ctaocrypt_test(void* args)
{
	
	///aaaaaaaaa   start
	
	#ifdef BENCHMARK

//
//
//volatile avr32_tc_t *tc = EXAMPLE_TC;
	//uint32_t timer = 10;
	///**
	 //* \note the call to sysclk_init() will disable all non-vital
	 //* peripheral clocks, except for the peripheral clocks explicitly
	 //* enabled in conf_clock.h.
	 //*/
	//sysclk_init();
	//// Enable the clock to the selected example Timer/counter peripheral module.
	//sysclk_enable_peripheral_clock(EXAMPLE_TC);
	//// Initialize the USART module for trace messages
	//init_dbg_rs232(sysclk_get_pba_hz());
	//// Disable the interrupts
	//cpu_irq_disable();
//
//#if defined (__GNUC__)
	//// Initialize interrupt vectors.
	//INTC_init_interrupts();
	//// Register the RTC interrupt handler to the interrupt controller.
	//INTC_register_interrupt(&tc_irq, EXAMPLE_TC_IRQ, EXAMPLE_TC_IRQ_PRIORITY);
//#endif
	//// Enable the interrupts
	//cpu_irq_enable();
	//// Initialize the timer module
	//tc_init(tc);
//
//
	
#endif
	//aaaaaaaaaaaa   end
	
	
	
	
	
	
	
	
    int ret = 0;

    ((func_args*)args)->return_code = -1; /* error state */

#if !defined(NO_BIG_INT)
    if (CheckCtcSettings() != 1)
        err_sys("Build vs runtime math mismatch\r\n", -1234);

#ifdef USE_FAST_MATH
    if (CheckFastMathSettings() != 1)
        err_sys("Build vs runtime fastmath FP_MAX_BITS mismatch\r\n", -1235);
#endif /* USE_FAST_MATH */
#endif /* !NO_BIG_INT */


#ifdef BENCHMARK


#ifndef NO_MD5
    bench_md5();
#endif
#ifndef NO_RABBIT
bench_rabbit();
#endif


#ifndef NO_RSA
bench_rsa();
#endif



#ifndef NO_AES
bench_aes(0);
bench_aes(1);
#endif
#ifdef HAVE_AESGCM
bench_aesgcm();
#endif
#ifdef HAVE_AESCCM
bench_aesccm();
#endif
#ifdef HAVE_CAMELLIA
bench_camellia();
#endif

#ifndef NO_DES3
bench_des();
#endif

printk("\n");




#endif

#ifdef TEST_LIBRARY


#ifndef NO_MD5
    if ( (ret = md5_test()) ) 
        err_sys("MD5      test failed!\r\n", ret);
    else
	    print_dbg("MD5      test passed!\r\n");	
#endif

#ifdef CYASSL_MD2
    if ( (ret = md2_test()) ) 
        err_sys("MD2      test failed!\r\n", ret);
    else
        print_dbg( "MD2      test passed!\r\n");
#endif

#ifndef NO_MD4
    if ( (ret = md4_test()) ) 
        err_sys("MD4      test failed!\r\n", ret);
    else
        print_dbg( "MD4      test passed!\r\n");
#endif

#ifndef NO_SHA
    if ( (ret = sha_test()) ) 
        err_sys("SHA      test failed!\r\n", ret);
    else
        print_dbg( "SHA      test passed!\r\n");
#endif

#ifndef NO_SHA256
    if ( (ret = sha256_test()) ) 
        err_sys("SHA-256  test failed!\r\n", ret);
    else
        print_dbg( "SHA-256  test passed!\r\n");
#endif

#ifdef CYASSL_SHA384
    if ( (ret = sha384_test()) ) 
        err_sys("SHA-384  test failed!\r\n", ret);
    else
        print_dbg( "SHA-384  test passed!\r\n");
#endif

#ifdef CYASSL_SHA512
    if ( (ret = sha512_test()) ) 
        err_sys("SHA-512  test failed!\r\n", ret);
    else
        print_dbg( "SHA-512  test passed!\r\n");
#endif

#ifdef CYASSL_RIPEMD
    if ( (ret = ripemd_test()) ) 
        err_sys("RIPEMD   test failed!\r\n", ret);
    else
        print_dbg( "RIPEMD   test passed!\r\n");
#endif

#ifdef HAVE_BLAKE2 
    if ( (ret = blake2b_test()) ) 
        err_sys("BLAKE2b  test failed!\r\n", ret);
    else
        print_dbg( "BLAKE2b  test passed!\r\n");
#endif

#ifndef NO_HMAC
    #ifndef NO_MD5
        if ( (ret = hmac_md5_test()) ) 
            err_sys("HMAC-MD5 test failed!\r\n", ret);
        else
            print_dbg( "HMAC-MD5 test passed!\r\n");
    #endif

    #ifndef NO_SHA
    if ( (ret = hmac_sha_test()) ) 
        err_sys("HMAC-SHA test failed!\r\n", ret);
    else
        print_dbg( "HMAC-SHA test passed!\r\n");
    #endif

    #ifndef NO_SHA256
        if ( (ret = hmac_sha256_test()) ) 
            err_sys("HMAC-SHA256 test failed!\r\n", ret);
        else
            print_dbg( "HMAC-SHA256 test passed!\r\n");
    #endif

    #ifdef CYASSL_SHA384
        if ( (ret = hmac_sha384_test()) ) 
            err_sys("HMAC-SHA384 test failed!\r\n", ret);
        else
            print_dbg( "HMAC-SHA384 test passed!\r\n");
    #endif

    #ifdef CYASSL_SHA512
        if ( (ret = hmac_sha512_test()) ) 
            err_sys("HMAC-SHA512 test failed!\r\n", ret);
        else
            print_dbg( "HMAC-SHA512 test passed!\r\n");
    #endif

#endif

#ifndef NO_RC4
    if ( (ret = arc4_test()) )
        err_sys("ARC4     test failed!\r\n", ret);
    else
        print_dbg( "ARC4     test passed!\r\n");
#endif

#ifndef NO_HC128
    if ( (ret = hc128_test()) )
        err_sys("HC-128   test failed!\r\n", ret);
    else
        print_dbg( "HC-128   test passed!\r\n");
#endif

#ifndef NO_RABBIT
    if ( (ret = rabbit_test()) )
        err_sys("Rabbit   test failed!\r\n", ret);
    else
        print_dbg( "Rabbit   test passed!\r\n");
#endif

#ifndef NO_DES3
    if ( (ret = des_test()) )
        err_sys("DES      test failed!\r\n", ret);
    else
        print_dbg( "DES      test passed!\r\n");
#endif

#ifndef NO_DES3
    if ( (ret = des3_test()) )
        err_sys("DES3     test failed!\r\n", ret);
    else
        print_dbg( "DES3     test passed!\r\n");
#endif

#ifndef NO_AES
    if ( (ret = aes_test()) )
        err_sys("AES-CBC-CTR      test failed!\r\n", ret);
    else
        print_dbg( "AES-CBC-CTR      test passed!\r\n");

#ifdef HAVE_AESGCM
    if ( (ret = aesgcm_test()) )
        err_sys("AES-GCM  test failed!\r\n", ret);
    else
        print_dbg( "AES-GCM  test passed!\r\n");
#endif

#ifdef HAVE_AESCCM
    if ( (ret = aesccm_test()) )
        err_sys("AES-CCM  test failed!\r\n", ret);
    else
        print_dbg( "AES-CCM  test passed!\r\n");
#endif
#endif

#ifdef HAVE_CAMELLIA
    if ( (ret = camellia_test()) )
        err_sys("CAMELLIA test failed!\r\n", ret);
    else
        print_dbg( "CAMELLIA test passed!\r\n");
#endif

    if ( (ret = random_test()) )
        err_sys("RANDOM   test failed!\r\n", ret);
    else
        print_dbg( "RANDOM   test passed!\r\n");

#ifndef NO_RSA
    if ( (ret = rsa_test()) ) 
        err_sys("RSA      test failed!\r\n", ret);
    else
        print_dbg( "RSA      test passed!\r\n");
#endif

#ifndef NO_DH
    if ( (ret = dh_test()) ) 
        err_sys("DH       test failed!\r\n", ret);
    else
        print_dbg( "DH       test passed!\r\n");
#endif

#ifndef NO_DSA
    if ( (ret = dsa_test()) ) 
        err_sys("DSA      test failed!\r\n", ret);
    else
        print_dbg( "DSA      test passed!\r\n");
#endif
    
#ifndef NO_PWDBASED
    if ( (ret = pwdbased_test()) ) 
        err_sys("PWDBASED test failed!\r\n", ret);
    else
        print_dbg( "PWDBASED test passed!\r\n");
#endif
    
#ifdef OPENSSL_EXTRA
    if ( (ret = openssl_test()) ) 
        err_sys("OPENSSL  test failed!\r\n", ret);
    else
        print_dbg( "OPENSSL  test passed!\r\n");
#endif

#ifdef HAVE_ECC
    if ( (ret = ecc_test()) ) 
        err_sys("ECC      test failed!\r\n", ret);
    else
        print_dbg( "ECC      test passed!\r\n");
#endif

#ifdef HAVE_LIBZ
    if ( (ret = compress_test()) ) 
        err_sys("COMPRESS test failed!\r\n", ret);
    else
        print_dbg( "COMPRESS test passed!\r\n");
#endif
#endif

    ((func_args*)args)->return_code = ret;
}


#ifndef NO_MAIN_DRIVER

#ifdef HAVE_CAVIUM

static int OpenNitroxDevice(int dma_mode,int dev_id)
{
   Csp1CoreAssignment core_assign;
   Uint32             device;

   if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID))
      return -1;
   if (Csp1GetDevType(&device))
      return -1;
   if (device != NPX_DEVICE) {
      if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT,
                (Uint32 *)&core_assign)!= 0)
         return -1;
   }
   CspShutdown(CAVIUM_DEV_ID);

   return CspInitialize(dma_mode, dev_id);
}

#endif /* HAVE_CAVIUM */

    /* so overall tests can pull in test function */

    int main_test(int argc, char** argv)
    {
        func_args args;

#ifdef HAVE_CAVIUM
        int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID);
        if (ret != 0)
            err_sys("Cavium OpenNitroxDevice failed", -1236);
#endif /* HAVE_CAVIUM */

        args.argc = argc;
        args.argv = argv;

        ctaocrypt_test(&args);

#ifdef HAVE_CAVIUM
        CspShutdown(CAVIUM_DEV_ID);
#endif
        return args.return_code;
    }

#endif /* NO_MAIN_DRIVER */




#ifdef TEST_LIBRARY


#ifdef CYASSL_MD2
int md2_test()
{
    Md2  md2;
    byte hash[MD2_DIGEST_SIZE];

    testVector a, b, c, d, e, f, g;
    testVector test_md2[7];
    int times = sizeof(test_md2) / sizeof(testVector), i;

    a.input  = "";
    a.output = "\x83\x50\xe5\xa3\xe2\x4c\x15\x3d\xf2\x27\x5c\x9f\x80\x69"
               "\x27\x73";
    a.inLen  = strlen(a.input);
    a.outLen = MD2_DIGEST_SIZE;

    b.input  = "a";
    b.output = "\x32\xec\x01\xec\x4a\x6d\xac\x72\xc0\xab\x96\xfb\x34\xc0"
               "\xb5\xd1";
    b.inLen  = strlen(b.input);
    b.outLen = MD2_DIGEST_SIZE;

    c.input  = "abc";
    c.output = "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde"
               "\xd6\xbb";
    c.inLen  = strlen(c.input);
    c.outLen = MD2_DIGEST_SIZE;

    d.input  = "message digest";
    d.output = "\xab\x4f\x49\x6b\xfb\x2a\x53\x0b\x21\x9f\xf3\x30\x31\xfe"
               "\x06\xb0";
    d.inLen  = strlen(d.input);
    d.outLen = MD2_DIGEST_SIZE;

    e.input  = "abcdefghijklmnopqrstuvwxyz";
    e.output = "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47"
               "\x94\x0b";
    e.inLen  = strlen(e.input);
    e.outLen = MD2_DIGEST_SIZE;

    f.input  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
               "6789";
    f.output = "\xda\x33\xde\xf2\xa4\x2d\xf1\x39\x75\x35\x28\x46\xc3\x03"
               "\x38\xcd";
    f.inLen  = strlen(f.input);
    f.outLen = MD2_DIGEST_SIZE;

    g.input  = "1234567890123456789012345678901234567890123456789012345678"
               "9012345678901234567890";
    g.output = "\xd5\x97\x6f\x79\xd8\x3d\x3a\x0d\xc9\x80\x6c\x3c\x66\xf3"
               "\xef\xd8";
    g.inLen  = strlen(g.input);
    g.outLen = MD2_DIGEST_SIZE;

    test_md2[0] = a;
    test_md2[1] = b;
    test_md2[2] = c;
    test_md2[3] = d;
    test_md2[4] = e;
    test_md2[5] = f;
    test_md2[6] = g;

    InitMd2(&md2);

    for (i = 0; i < times; ++i) {
        Md2Update(&md2, (byte*)test_md2[i].input, (word32)test_md2[i].inLen);
        Md2Final(&md2, hash);

        if (memcmp(hash, test_md2[i].output, MD2_DIGEST_SIZE) != 0)
            return -155 - i;
    }

    return 0;
}
#endif 

#ifndef NO_MD5
int md5_test(void)
{
    Md5  md5;
    byte hash[MD5_DIGEST_SIZE];






    testVector a, b, c, d, e;
    testVector test_md5[5];
    int times = sizeof(test_md5) / sizeof(testVector), i;

    a.input  = "abc";
    a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f"
               "\x72";
    a.inLen  = strlen(a.input);
    a.outLen = MD5_DIGEST_SIZE;

    b.input  = "message digest";
    b.output = "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61"
               "\xd0";
    b.inLen  = strlen(b.input);
    b.outLen = MD5_DIGEST_SIZE;

    c.input  = "abcdefghijklmnopqrstuvwxyz";
    c.output = "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1"
               "\x3b";
    c.inLen  = strlen(c.input);
    c.outLen = MD5_DIGEST_SIZE;

    d.input  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
               "6789";
    d.output = "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d"
               "\x9f";
    d.inLen  = strlen(d.input);
    d.outLen = MD5_DIGEST_SIZE;

    e.input  = "1234567890123456789012345678901234567890123456789012345678"
               "9012345678901234567890";
    e.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6"
               "\x7a";
    e.inLen  = strlen(e.input);
    e.outLen = MD5_DIGEST_SIZE;

    test_md5[0] = a;
    test_md5[1] = b;
    test_md5[2] = c;
    test_md5[3] = d;
    test_md5[4] = e;

    InitMd5(&md5);


    for (i = 0; i < times; ++i) {
        Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen);
        Md5Final(&md5, hash);

        if (memcmp(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0)
            return -5 - i;
    }

    return 0;
}
#endif /* NO_MD5 */


#ifndef NO_MD4

int md4_test(void)
{
    Md4  md4;
    byte hash[MD4_DIGEST_SIZE];

    testVector a, b, c, d, e, f, g;
    testVector test_md4[7];
    int times = sizeof(test_md4) / sizeof(testVector), i;

    a.input  = "";
    a.output = "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89" 
               "\xc0";
    a.inLen  = strlen(a.input);
    a.outLen = MD4_DIGEST_SIZE;

    b.input  = "a";
    b.output = "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb" 
               "\x24";
    b.inLen  = strlen(b.input);
    b.outLen = MD4_DIGEST_SIZE; 

    c.input  = "abc";
    c.output = "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72" 
               "\x9d";
    c.inLen  = strlen(c.input);
    c.outLen = MD4_DIGEST_SIZE;

    d.input  = "message digest";
    d.output = "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01" 
               "\x4b";
    d.inLen  = strlen(d.input);
    d.outLen = MD4_DIGEST_SIZE;

    e.input  = "abcdefghijklmnopqrstuvwxyz";
    e.output = "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d" 
               "\xa9";
    e.inLen  = strlen(e.input);
    e.outLen = MD4_DIGEST_SIZE;

    f.input  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345"
               "6789";
    f.output = "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0" 
               "\xe4";
    f.inLen  = strlen(f.input);
    f.outLen = MD4_DIGEST_SIZE;

    g.input  = "1234567890123456789012345678901234567890123456789012345678"
               "9012345678901234567890";
    g.output = "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05" 
               "\x36";
    g.inLen  = strlen(g.input);
    g.outLen = MD4_DIGEST_SIZE;

    test_md4[0] = a;
    test_md4[1] = b;
    test_md4[2] = c;
    test_md4[3] = d;
    test_md4[4] = e;
    test_md4[5] = f;
    test_md4[6] = g;

    InitMd4(&md4);

    for (i = 0; i < times; ++i) {
        Md4Update(&md4, (byte*)test_md4[i].input, (word32)test_md4[i].inLen);
        Md4Final(&md4, hash);

        if (memcmp(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0)
            return -205 - i;
    }

    return 0;
}

#endif /* NO_MD4 */

#ifndef NO_SHA

int sha_test(void)
{
    Sha  sha;
    byte hash[SHA_DIGEST_SIZE];

    testVector a, b, c, d;
    testVector test_sha[4];
    int times = sizeof(test_sha) / sizeof(struct testVector), i;

    a.input  = "abc";
    a.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2"
               "\x6C\x9C\xD0\xD8\x9D";
    a.inLen  = strlen(a.input);
    a.outLen = SHA_DIGEST_SIZE;

    b.input  = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
    b.output = "\x84\x98\x3E\x44\x1C\x3B\xD2\x6E\xBA\xAE\x4A\xA1\xF9\x51\x29"
               "\xE5\xE5\x46\x70\xF1";
    b.inLen  = strlen(b.input);
    b.outLen = SHA_DIGEST_SIZE;

    c.input  = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
               "aaaaaa";
    c.output = "\x00\x98\xBA\x82\x4B\x5C\x16\x42\x7B\xD7\xA1\x12\x2A\x5A\x44"
               "\x2A\x25\xEC\x64\x4D";
    c.inLen  = strlen(c.input);
    c.outLen = SHA_DIGEST_SIZE; 

    d.input  = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
               "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
               "aaaaaaaaaa";
    d.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7"
               "\x53\x99\x5E\x26\xA0";
    d.inLen  = strlen(d.input);
    d.outLen = SHA_DIGEST_SIZE;

    test_sha[0] = a;
    test_sha[1] = b;
    test_sha[2] = c;
    test_sha[3] = d;

    InitSha(&sha);

    for (i = 0; i < times; ++i) {
        ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen);
        ShaFinal(&sha, hash);

        if (memcmp(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0)
            return -10 - i;
    }

    return 0;
}

#endif /* NO_SHA */

#ifdef CYASSL_RIPEMD
int ripemd_test(void)
{
    RipeMd  ripemd;
    byte hash[RIPEMD_DIGEST_SIZE];

    testVector a, b, c, d;
    testVector test_ripemd[4];
    int times = sizeof(test_ripemd) / sizeof(struct testVector), i;

    a.input  = "abc";
    a.output = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6"
               "\xb0\x87\xf1\x5a\x0b\xfc";
    a.inLen  = strlen(a.input);
    a.outLen = RIPEMD_DIGEST_SIZE;

    b.input  = "message digest";
    b.output = "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8"
               "\x5f\xfa\x21\x59\x5f\x36";
    b.inLen  = strlen(b.input);
    b.outLen = RIPEMD_DIGEST_SIZE;

    c.input  = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; 
    c.output = "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc"
               "\xf4\x9a\xda\x62\xeb\x2b";
    c.inLen  = strlen(c.input);
    c.outLen = RIPEMD_DIGEST_SIZE;

    d.input  = "12345678901234567890123456789012345678901234567890123456"
               "789012345678901234567890";
    d.output = "\x9b\x75\x2e\x45\x57\x3d\x4b\x39\xf4\xdb\xd3\x32\x3c\xab"
               "\x82\xbf\x63\x32\x6b\xfb"; 
    d.inLen  = strlen(d.input);
    d.outLen = RIPEMD_DIGEST_SIZE;

    test_ripemd[0] = a;
    test_ripemd[1] = b;
    test_ripemd[2] = c;
    test_ripemd[3] = d;

    InitRipeMd(&ripemd);

    for (i = 0; i < times; ++i) {
        RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input,
                     (word32)test_ripemd[i].inLen);
        RipeMdFinal(&ripemd, hash);

        if (memcmp(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0)
            return -10 - i;
    }

    return 0;
}
#endif /* CYASSL_RIPEMD */


#ifdef HAVE_BLAKE2


#define BLAKE2_TESTS 3

static const byte blake2b_vec[BLAKE2_TESTS][BLAKE2B_OUTBYTES] =
{
  {
    0x78, 0x6A, 0x02, 0xF7, 0x42, 0x01, 0x59, 0x03,
    0xC6, 0xC6, 0xFD, 0x85, 0x25, 0x52, 0xD2, 0x72,
    0x91, 0x2F, 0x47, 0x40, 0xE1, 0x58, 0x47, 0x61,
    0x8A, 0x86, 0xE2, 0x17, 0xF7, 0x1F, 0x54, 0x19,
    0xD2, 0x5E, 0x10, 0x31, 0xAF, 0xEE, 0x58, 0x53,
    0x13, 0x89, 0x64, 0x44, 0x93, 0x4E, 0xB0, 0x4B,
    0x90, 0x3A, 0x68, 0x5B, 0x14, 0x48, 0xB7, 0x55,
    0xD5, 0x6F, 0x70, 0x1A, 0xFE, 0x9B, 0xE2, 0xCE
  },
  {
    0x2F, 0xA3, 0xF6, 0x86, 0xDF, 0x87, 0x69, 0x95,
    0x16, 0x7E, 0x7C, 0x2E, 0x5D, 0x74, 0xC4, 0xC7,
    0xB6, 0xE4, 0x8F, 0x80, 0x68, 0xFE, 0x0E, 0x44,
    0x20, 0x83, 0x44, 0xD4, 0x80, 0xF7, 0x90, 0x4C,
    0x36, 0x96, 0x3E, 0x44, 0x11, 0x5F, 0xE3, 0xEB,
    0x2A, 0x3A, 0xC8, 0x69, 0x4C, 0x28, 0xBC, 0xB4,
    0xF5, 0xA0, 0xF3, 0x27, 0x6F, 0x2E, 0x79, 0x48,
    0x7D, 0x82, 0x19, 0x05, 0x7A, 0x50, 0x6E, 0x4B
  },
  {
    0x1C, 0x08, 0x79, 0x8D, 0xC6, 0x41, 0xAB, 0xA9,
    0xDE, 0xE4, 0x35, 0xE2, 0x25, 0x19, 0xA4, 0x72,
    0x9A, 0x09, 0xB2, 0xBF, 0xE0, 0xFF, 0x00, 0xEF,
    0x2D, 0xCD, 0x8E, 0xD6, 0xF8, 0xA0, 0x7D, 0x15,
    0xEA, 0xF4, 0xAE, 0xE5, 0x2B, 0xBF, 0x18, 0xAB,
    0x56, 0x08, 0xA6, 0x19, 0x0F, 0x70, 0xB9, 0x04,
    0x86, 0xC8, 0xA7, 0xD4, 0x87, 0x37, 0x10, 0xB1,
    0x11, 0x5D, 0x3D, 0xEB, 0xBB, 0x43, 0x27, 0xB5
  }
};



int blake2b_test(void)
{
    Blake2b b2b;
    byte    digest[64];
    byte    input[64];
    int     i;

    for (i = 0; i < (int)sizeof(input); i++)
        input[i] = (byte)i;

    for (i = 0; i < BLAKE2_TESTS; i++) {
        InitBlake2b(&b2b, 64);
        Blake2bUpdate(&b2b, input, i);
        Blake2bFinal(&b2b, digest, 64);

        if (memcmp(digest, blake2b_vec[i], 64) != 0) {
            return -300 - i;
        }
    }

    return 0;
}
#endif /* HAVE_BLAKE2 */


#ifndef NO_SHA256
int sha256_test(void)
{
    Sha256 sha;
    byte   hash[SHA256_DIGEST_SIZE];

    testVector a, b;
    testVector test_sha[2];
    int times = sizeof(test_sha) / sizeof(struct testVector), i;

    a.input  = "abc";
    a.output = "\xBA\x78\x16\xBF\x8F\x01\xCF\xEA\x41\x41\x40\xDE\x5D\xAE\x22"
               "\x23\xB0\x03\x61\xA3\x96\x17\x7A\x9C\xB4\x10\xFF\x61\xF2\x00"
               "\x15\xAD";
    a.inLen  = strlen(a.input);
    a.outLen = SHA256_DIGEST_SIZE;

    b.input  = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
    b.output = "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60"
               "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB"
               "\x06\xC1";
    b.inLen  = strlen(b.input);
    b.outLen = SHA256_DIGEST_SIZE;

    test_sha[0] = a;
    test_sha[1] = b;

    InitSha256(&sha);

    for (i = 0; i < times; ++i) {
        Sha256Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen);
        Sha256Final(&sha, hash);

        if (memcmp(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0)
            return -10 - i;
    }

    return 0;
}
#endif


#ifdef CYASSL_SHA512
int sha512_test(void)
{
    Sha512 sha;
    byte   hash[SHA512_DIGEST_SIZE];

    testVector a, b;
    testVector test_sha[2];
    int times = sizeof(test_sha) / sizeof(struct testVector), i;

    a.input  = "abc";
    a.output = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41"
               "\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55"
               "\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3"
               "\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f"
               "\xa5\x4c\xa4\x9f";
    a.inLen  = strlen(a.input);
    a.outLen = SHA512_DIGEST_SIZE;

    b.input  = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi"
               "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
    b.output = "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14"
               "\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88"
               "\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4"
               "\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b"
               "\x87\x4b\xe9\x09"; 
    b.inLen  = strlen(b.input);
    b.outLen = SHA512_DIGEST_SIZE;

    test_sha[0] = a;
    test_sha[1] = b;

    InitSha512(&sha);

    for (i = 0; i < times; ++i) {
        Sha512Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen);
        Sha512Final(&sha, hash);

        if (memcmp(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0)
            return -10 - i;
    }

    return 0;
}
#endif


#ifdef CYASSL_SHA384
int sha384_test(void)
{
    Sha384 sha;
    byte   hash[SHA384_DIGEST_SIZE];

    testVector a, b;
    testVector test_sha[2];
    int times = sizeof(test_sha) / sizeof(struct testVector), i;

    a.input  = "abc";
    a.output = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50"
               "\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff"
               "\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34"
               "\xc8\x25\xa7";
    a.inLen  = strlen(a.input);
    a.outLen = SHA384_DIGEST_SIZE;

    b.input  = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi"
               "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
    b.output = "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b"
               "\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0"
               "\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91"
               "\x74\x60\x39";
    b.inLen  = strlen(b.input);
    b.outLen = SHA384_DIGEST_SIZE; 

    test_sha[0] = a;
    test_sha[1] = b;

    InitSha384(&sha);

    for (i = 0; i < times; ++i) {
        Sha384Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen);
        Sha384Final(&sha, hash);

        if (memcmp(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0)
            return -10 - i;
    }

    return 0;
}
#endif /* CYASSL_SHA384 */


#if !defined(NO_HMAC) && !defined(NO_MD5)
int hmac_md5_test(void)
{
    Hmac hmac;
    byte hash[MD5_DIGEST_SIZE];

    const char* keys[]=
    {
        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
        "Jefe",
        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
    };

    testVector a, b, c;
    testVector test_hmac[3];

    int times = sizeof(test_hmac) / sizeof(testVector), i;

    a.input  = "Hi There";
    a.output = "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc"
               "\x9d";
    a.inLen  = strlen(a.input);
    a.outLen = MD5_DIGEST_SIZE;

    b.input  = "what do ya want for nothing?";
    b.output = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7"
               "\x38";
    b.inLen  = strlen(b.input);
    b.outLen = MD5_DIGEST_SIZE;

    c.input  = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD";
    c.output = "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3"
               "\xf6";
    c.inLen  = strlen(c.input);
    c.outLen = MD5_DIGEST_SIZE;

    test_hmac[0] = a;
    test_hmac[1] = b;
    test_hmac[2] = c;

    for (i = 0; i < times; ++i) {
#ifdef HAVE_CAVIUM
        if (i == 1)
            continue; /* driver can't handle keys <= bytes */
        if (HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0)
            return -20009; 
#endif
        HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)strlen(keys[i]));
        HmacUpdate(&hmac, (byte*)test_hmac[i].input,
                   (word32)test_hmac[i].inLen);
        HmacFinal(&hmac, hash);

        if (memcmp(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0)
            return -20 - i;
#ifdef HAVE_CAVIUM
        HmacFreeCavium(&hmac);
#endif
    }

    return 0;
}
#endif /* NO_HMAC && NO_MD5 */

#if !defined(NO_HMAC) && !defined(NO_SHA)
int hmac_sha_test(void)
{
    Hmac hmac;
    byte hash[SHA_DIGEST_SIZE];

    const char* keys[]=
    {
        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
                                                                "\x0b\x0b\x0b",
        "Jefe",
        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
                                                                "\xAA\xAA\xAA"
    };

    testVector a, b, c;
    testVector test_hmac[3];

    int times = sizeof(test_hmac) / sizeof(testVector), i;

    a.input  = "Hi There";
    a.output = "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c"
               "\x8e\xf1\x46\xbe\x00";
    a.inLen  = strlen(a.input);
    a.outLen = SHA_DIGEST_SIZE;

    b.input  = "what do ya want for nothing?";
    b.output = "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf"
               "\x9c\x25\x9a\x7c\x79";
    b.inLen  = strlen(b.input);
    b.outLen = SHA_DIGEST_SIZE;

    c.input  = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD";
    c.output = "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b"
               "\x4f\x63\xf1\x75\xd3";
    c.inLen  = strlen(c.input);
    c.outLen = SHA_DIGEST_SIZE;

    test_hmac[0] = a;
    test_hmac[1] = b;
    test_hmac[2] = c;

    for (i = 0; i < times; ++i) {
#ifdef HAVE_CAVIUM
        if (i == 1)
            continue; /* driver can't handle keys <= bytes */
        if (HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0)
            return -20010; 
#endif
        HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)strlen(keys[i]));
        HmacUpdate(&hmac, (byte*)test_hmac[i].input,
                   (word32)test_hmac[i].inLen);
        HmacFinal(&hmac, hash);

        if (memcmp(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0)
            return -20 - i;
#ifdef HAVE_CAVIUM
        HmacFreeCavium(&hmac);
#endif
    }

    return 0;
}
#endif


#if !defined(NO_HMAC) && !defined(NO_SHA256)
int hmac_sha256_test(void)
{
    Hmac hmac;
    byte hash[SHA256_DIGEST_SIZE];

    const char* keys[]=
    {
        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
                                                                "\x0b\x0b\x0b",
        "Jefe",
        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
                                                                "\xAA\xAA\xAA"
    };

    testVector a, b, c;
    testVector test_hmac[3];

    int times = sizeof(test_hmac) / sizeof(testVector), i;

    a.input  = "Hi There";
    a.output = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1"
               "\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32"
               "\xcf\xf7";
    a.inLen  = strlen(a.input);
    a.outLen = SHA256_DIGEST_SIZE;

    b.input  = "what do ya want for nothing?";
    b.output = "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75"
               "\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec"
               "\x38\x43";
    b.inLen  = strlen(b.input);
    b.outLen = SHA256_DIGEST_SIZE;

    c.input  = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD";
    c.output = "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81"
               "\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5"
               "\x65\xfe";
    c.inLen  = strlen(c.input);
    c.outLen = SHA256_DIGEST_SIZE;

    test_hmac[0] = a;
    test_hmac[1] = b;
    test_hmac[2] = c;

    for (i = 0; i < times; ++i) {
#ifdef HAVE_CAVIUM
        if (i == 1)
            continue; /* driver can't handle keys <= bytes */
        if (HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0)
            return -20011; 
#endif
        HmacSetKey(&hmac, SHA256, (byte*)keys[i], (word32)strlen(keys[i]));
        HmacUpdate(&hmac, (byte*)test_hmac[i].input,
                   (word32)test_hmac[i].inLen);
        HmacFinal(&hmac, hash);

        if (memcmp(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0)
            return -20 - i;
#ifdef HAVE_CAVIUM
        HmacFreeCavium(&hmac);
#endif
    }

    return 0;
}
#endif


#if !defined(NO_HMAC) && defined(CYASSL_SHA384)
int hmac_sha384_test(void)
{
    Hmac hmac;
    byte hash[SHA384_DIGEST_SIZE];

    const char* keys[]=
    {
        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
                                                                "\x0b\x0b\x0b",
        "Jefe",
        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
                                                                "\xAA\xAA\xAA"
    };

    testVector a, b, c;
    testVector test_hmac[3];

    int times = sizeof(test_hmac) / sizeof(testVector), i;

    a.input  = "Hi There";
    a.output = "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90"
               "\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb"
               "\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2"
               "\xfa\x9c\xb6";
    a.inLen  = strlen(a.input);
    a.outLen = SHA384_DIGEST_SIZE;

    b.input  = "what do ya want for nothing?";
    b.output = "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b"
               "\x1b\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22"
               "\x44\x5e\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa"
               "\xb2\x16\x49";
    b.inLen  = strlen(b.input);
    b.outLen = SHA384_DIGEST_SIZE;

    c.input  = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD";
    c.output = "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8"
               "\x6f\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66"
               "\x14\x4b\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01"
               "\xa3\x4f\x27";
    c.inLen  = strlen(c.input);
    c.outLen = SHA384_DIGEST_SIZE;

    test_hmac[0] = a;
    test_hmac[1] = b;
    test_hmac[2] = c;

    for (i = 0; i < times; ++i) {
        HmacSetKey(&hmac, SHA384, (byte*)keys[i], (word32)strlen(keys[i]));
        HmacUpdate(&hmac, (byte*)test_hmac[i].input,
                   (word32)test_hmac[i].inLen);
        HmacFinal(&hmac, hash);

        if (memcmp(hash, test_hmac[i].output, SHA384_DIGEST_SIZE) != 0)
            return -20 - i;
    }

    return 0;
}
#endif


#if !defined(NO_HMAC) && defined(CYASSL_SHA512)
int hmac_sha512_test(void)
{
    Hmac hmac;
    byte hash[SHA512_DIGEST_SIZE];

    const char* keys[]=
    {
        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
                                                                "\x0b\x0b\x0b",
        "Jefe",
        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
                                                                "\xAA\xAA\xAA"
    };

    testVector a, b, c;
    testVector test_hmac[3];

    int times = sizeof(test_hmac) / sizeof(testVector), i;

    a.input  = "Hi There";
    a.output = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c"
               "\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1"
               "\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae"
               "\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20"
               "\x3a\x12\x68\x54";
    a.inLen  = strlen(a.input);
    a.outLen = SHA512_DIGEST_SIZE;

    b.input  = "what do ya want for nothing?";
    b.output = "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0"
               "\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25"
               "\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8"
               "\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a"
               "\x38\xbc\xe7\x37";
    b.inLen  = strlen(b.input);
    b.outLen = SHA512_DIGEST_SIZE;

    c.input  = "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
               "\xDD\xDD\xDD\xDD\xDD\xDD";
    c.output = "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b"
               "\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27"
               "\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e"
               "\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59"
               "\xe1\x32\x92\xfb";
    c.inLen  = strlen(c.input);
    c.outLen = SHA512_DIGEST_SIZE;

    test_hmac[0] = a;
    test_hmac[1] = b;
    test_hmac[2] = c;

    for (i = 0; i < times; ++i) {
        HmacSetKey(&hmac, SHA512, (byte*)keys[i], (word32)strlen(keys[i]));
        HmacUpdate(&hmac, (byte*)test_hmac[i].input,
                   (word32)test_hmac[i].inLen);
        HmacFinal(&hmac, hash);

        if (memcmp(hash, test_hmac[i].output, SHA512_DIGEST_SIZE) != 0)
            return -20 - i;
    }

    return 0;
}
#endif


#ifndef NO_RC4
int arc4_test(void)
{
    byte cipher[16];
    byte plain[16];

    const char* keys[] = 
    {           
        "\x01\x23\x45\x67\x89\xab\xcd\xef",
        "\x01\x23\x45\x67\x89\xab\xcd\xef",
        "\x00\x00\x00\x00\x00\x00\x00\x00",
        "\xef\x01\x23\x45"
    };

    testVector a, b, c, d;
    testVector test_arc4[4];

    int times = sizeof(test_arc4) / sizeof(testVector), i;

    a.input  = "\x01\x23\x45\x67\x89\xab\xcd\xef";
    a.output = "\x75\xb7\x87\x80\x99\xe0\xc5\x96";
    a.inLen  = 8;
    a.outLen = 8;

    b.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    b.output = "\x74\x94\xc2\xe7\x10\x4b\x08\x79";
    b.inLen  = 8;
    b.outLen = 8;

    c.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    c.output = "\xde\x18\x89\x41\xa3\x37\x5d\x3a";
    c.inLen  = 8;
    c.outLen = 8;

    d.input  = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    d.output = "\xd6\xa1\x41\xa7\xec\x3c\x38\xdf\xbd\x61";
    d.inLen  = 10;
    d.outLen = 10;

    test_arc4[0] = a;
    test_arc4[1] = b;
    test_arc4[2] = c;
    test_arc4[3] = d;

    for (i = 0; i < times; ++i) {
        Arc4 enc;
        Arc4 dec;
        int  keylen = 8;  /* strlen with key 0x00 not good */
        if (i == 3)
            keylen = 4;

#ifdef HAVE_CAVIUM
        if (Arc4InitCavium(&enc, CAVIUM_DEV_ID) != 0)
            return -20001; 
        if (Arc4InitCavium(&dec, CAVIUM_DEV_ID) != 0)
            return -20002; 
#endif

        Arc4SetKey(&enc, (byte*)keys[i], keylen);
        Arc4SetKey(&dec, (byte*)keys[i], keylen);

        Arc4Process(&enc, cipher, (byte*)test_arc4[i].input,
                    (word32)test_arc4[i].outLen);
        Arc4Process(&dec, plain,  cipher, (word32)test_arc4[i].outLen);

        if (memcmp(plain, test_arc4[i].input, test_arc4[i].outLen))
            return -20 - i;

        if (memcmp(cipher, test_arc4[i].output, test_arc4[i].outLen))
            return -20 - 5 - i;

#ifdef HAVE_CAVIUM
        Arc4FreeCavium(&enc);
        Arc4FreeCavium(&dec);
#endif
    }

    return 0;
}
#endif


int hc128_test(void)
{
#ifdef HAVE_HC128
    byte cipher[16];
    byte plain[16];

    const char* keys[] = 
    {           
        "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x00\x53\xA6\xF9\x4C\x9F\xF2\x45\x98\xEB\x3E\x91\xE4\x37\x8A\xDD",
        "\x0F\x62\xB5\x08\x5B\xAE\x01\x54\xA7\xFA\x4D\xA0\xF3\x46\x99\xEC"
    };

    const char* ivs[] =
    {
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x0D\x74\xDB\x42\xA9\x10\x77\xDE\x45\xAC\x13\x7A\xE1\x48\xAF\x16",
        "\x28\x8F\xF6\x5D\xC4\x2B\x92\xF9\x60\xC7\x2E\x95\xFC\x63\xCA\x31"
    };


    testVector a, b, c, d;
    testVector test_hc128[4];

    int times = sizeof(test_hc128) / sizeof(testVector), i;

    a.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    a.output = "\x37\x86\x02\xB9\x8F\x32\xA7\x48";
    a.inLen  = 8;
    a.outLen = 8;

    b.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    b.output = "\x33\x7F\x86\x11\xC6\xED\x61\x5F";
    b.inLen  = 8;
    b.outLen = 8;

    c.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    c.output = "\x2E\x1E\xD1\x2A\x85\x51\xC0\x5A";
    c.inLen  = 8;
    c.outLen = 8;

    d.input  = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
    d.output = "\x1C\xD8\xAE\xDD\xFE\x52\xE2\x17\xE8\x35\xD0\xB7\xE8\x4E\x29";
    d.inLen  = 15;
    d.outLen = 15;

    test_hc128[0] = a;
    test_hc128[1] = b;
    test_hc128[2] = c;
    test_hc128[3] = d;

    for (i = 0; i < times; ++i) {
        HC128 enc;
        HC128 dec;

        /* align keys/ivs in plain/cipher buffers */
        memcpy(plain,  keys[i], 16); 
        memcpy(cipher, ivs[i],  16); 

        Hc128_SetKey(&enc, plain, cipher);
        Hc128_SetKey(&dec, plain, cipher);

        /* align input */
        memcpy(plain, test_hc128[i].input, test_hc128[i].outLen);
        Hc128_Process(&enc, cipher, plain,  (word32)test_hc128[i].outLen);
        Hc128_Process(&dec, plain,  cipher, (word32)test_hc128[i].outLen);

        if (memcmp(plain, test_hc128[i].input, test_hc128[i].outLen))
            return -120 - i;

        if (memcmp(cipher, test_hc128[i].output, test_hc128[i].outLen))
            return -120 - 5 - i;
    }

#endif /* HAVE_HC128 */
    return 0;
}


#ifndef NO_RABBIT
int rabbit_test(void)
{
    byte cipher[16];
    byte plain[16];

    const char* keys[] = 
    {           
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
        "\xAC\xC3\x51\xDC\xF1\x62\xFC\x3B\xFE\x36\x3D\x2E\x29\x13\x28\x91"
    };

    const char* ivs[] =
    {
        "\x00\x00\x00\x00\x00\x00\x00\x00",
        "\x59\x7E\x26\xC1\x75\xF5\x73\xC3",
        0
    };

    testVector a, b, c;
    testVector test_rabbit[3];

    int times = sizeof(test_rabbit) / sizeof(testVector), i;

    a.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    a.output = "\xED\xB7\x05\x67\x37\x5D\xCD\x7C";
    a.inLen  = 8;
    a.outLen = 8;

    b.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    b.output = "\x6D\x7D\x01\x22\x92\xCC\xDC\xE0";
    b.inLen  = 8;
    b.outLen = 8;

    c.input  = "\x00\x00\x00\x00\x00\x00\x00\x00";
    c.output = "\x9C\x51\xE2\x87\x84\xC3\x7F\xE9";
    c.inLen  = 8;
    c.outLen = 8;

    test_rabbit[0] = a;
    test_rabbit[1] = b;
    test_rabbit[2] = c;

    for (i = 0; i < times; ++i) {
        Rabbit enc;
        Rabbit dec;
        byte*  iv;

        /* align keys/ivs in plain/cipher buffers */
        memcpy(plain,  keys[i], 16);
        if (ivs[i]) {
            memcpy(cipher, ivs[i],   8);
            iv = cipher;
        } else
            iv = NULL;
        RabbitSetKey(&enc, plain, iv);
        RabbitSetKey(&dec, plain, iv);

        /* align input */
        memcpy(plain, test_rabbit[i].input, test_rabbit[i].outLen);
        RabbitProcess(&enc, cipher, plain,  (word32)test_rabbit[i].outLen);
        RabbitProcess(&dec, plain,  cipher, (word32)test_rabbit[i].outLen);

        if (memcmp(plain, test_rabbit[i].input, test_rabbit[i].outLen))
            return -130 - i;

        if (memcmp(cipher, test_rabbit[i].output, test_rabbit[i].outLen))
            return -130 - 5 - i;
    }

    return 0;
}
#endif /* NO_RABBIT */


#ifndef NO_DES3
int des_test(void)
{
    const byte vector[] = { /* "now is the time for all " w/o trailing 0 */
        0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
        0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
        0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
    };

    byte plain[24];
    byte cipher[24];

    Des enc;
    Des dec;

    const byte key[] = 
    {
        0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
    };

    const byte iv[] = 
    {
        0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef
    };

    const byte verify[] = 
    {
        0x8b,0x7c,0x52,0xb0,0x01,0x2b,0x6c,0xb8,
        0x4f,0x0f,0xeb,0xf3,0xfb,0x5f,0x86,0x73,
        0x15,0x85,0xb3,0x22,0x4b,0x86,0x2b,0x4b
    };


    Des_SetKey(&enc, key, iv, DES_ENCRYPTION);
    Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector));
    Des_SetKey(&dec, key, iv, DES_DECRYPTION);
    Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher));

    if (memcmp(plain, vector, sizeof(plain)))
        return -31;

    if (memcmp(cipher, verify, sizeof(cipher)))
        return -32;

    return 0;
}
#endif /* NO_DES3 */


#ifndef NO_DES3
int des3_test(void)
{
    const byte vector[] = { /* "Now is the time for all " w/o trailing 0 */
        0x4e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
        0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
        0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
    };

    byte plain[24];
    byte cipher[24];

    Des3 enc;
    Des3 dec;

    const byte key3[] = 
    {
        0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
        0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10,
        0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
    };
    const byte iv3[] = 
    {
        0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef,
        0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
        0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81
        
    };

    const byte verify3[] = 
    {
        0x43,0xa0,0x29,0x7e,0xd1,0x84,0xf8,0x0e,
        0x89,0x64,0x84,0x32,0x12,0xd5,0x08,0x98,
        0x18,0x94,0x15,0x74,0x87,0x12,0x7d,0xb0
    };


#ifdef HAVE_CAVIUM
    if (Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0)
        return -20005; 
    if (Des3_InitCavium(&dec, CAVIUM_DEV_ID) != 0)
        return -20006; 
#endif
    Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION);
    Des3_SetKey(&dec, key3, iv3, DES_DECRYPTION);
    Des3_CbcEncrypt(&enc, cipher, vector, sizeof(vector));
    Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher));

    if (memcmp(plain, vector, sizeof(plain)))
        return -33;

    if (memcmp(cipher, verify3, sizeof(cipher)))
        return -34;

#ifdef HAVE_CAVIUM
    Des3_FreeCavium(&enc);
    Des3_FreeCavium(&dec);
#endif
    return 0;
}
#endif /* NO_DES */


#ifndef NO_AES
int aes_test(void)
{
    Aes enc;
    Aes dec;

    const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */
        0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
        0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
        0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
    };

    const byte verify[] = 
    {
        0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53,
        0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb
    };

    byte key[] = "0123456789abcdef   ";  /* align */
    byte iv[]  = "1234567890abcdef   ";  /* align */

    byte cipher[AES_BLOCK_SIZE * 4];
    byte plain [AES_BLOCK_SIZE * 4];

#ifdef HAVE_CAVIUM
        if (AesInitCavium(&enc, CAVIUM_DEV_ID) != 0)
            return -20003; 
        if (AesInitCavium(&dec, CAVIUM_DEV_ID) != 0)
            return -20004; 
#endif
    AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION);
    AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION);

    AesCbcEncrypt(&enc, cipher, msg,   AES_BLOCK_SIZE);
    AesCbcDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE);

    if (memcmp(plain, msg, AES_BLOCK_SIZE))
        return -60;

    if (memcmp(cipher, verify, AES_BLOCK_SIZE))
        return -61;

#ifdef HAVE_CAVIUM
        AesFreeCavium(&enc);
        AesFreeCavium(&dec);
#endif
#ifdef CYASSL_AES_COUNTER
    {
        const byte ctrKey[] = 
        {
            0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,
            0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c
        };

        const byte ctrIv[] =
        {
            0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
            0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
        };


        const byte ctrPlain[] =
        {
            0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,
            0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a,
            0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,
            0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51,
            0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,
            0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef,
            0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,
            0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10
        };

        const byte ctrCipher[] =
        {
            0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26,
            0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce,
            0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff,
            0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff,
            0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e,
            0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab,
            0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1,
            0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee
        };

        AesSetKeyDirect(&enc, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION);
        /* Ctr only uses encrypt, even on key setup */
        AesSetKeyDirect(&dec, ctrKey, AES_BLOCK_SIZE, ctrIv, AES_ENCRYPTION);

        AesCtrEncrypt(&enc, cipher, ctrPlain, AES_BLOCK_SIZE*4);
        AesCtrEncrypt(&dec, plain, cipher, AES_BLOCK_SIZE*4);

        if (memcmp(plain, ctrPlain, AES_BLOCK_SIZE*4))
            return -66;

        if (memcmp(cipher, ctrCipher, AES_BLOCK_SIZE*4))
            return -67;
    }
#endif /* CYASSL_AES_COUNTER */

    return 0;
}

#ifdef HAVE_AESGCM
int aesgcm_test(void)
{
    Aes enc;

    /*
     * This is Test Case 16 from the document Galois/
     * Counter Mode of Operation (GCM) by McGrew and
     * Viega.
     */
    const byte k[] =
    {
        0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
        0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
        0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
        0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08
    };

    const byte iv[] =
    {
        0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
        0xde, 0xca, 0xf8, 0x88
    };
    
    const byte p[] =
    {
        0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
        0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
        0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
        0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
        0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
        0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
        0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
        0xba, 0x63, 0x7b, 0x39
    };
    
    const byte a[] =
    {
        0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
        0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
        0xab, 0xad, 0xda, 0xd2
    };
    
    const byte c[] =
    {
        0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
        0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
        0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
        0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
        0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
        0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
        0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
        0xbc, 0xc9, 0xf6, 0x62
    };

    const byte t[] =
    {
        0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
        0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b
    };

    byte t2[sizeof(t)];
    byte p2[sizeof(c)];
    byte c2[sizeof(p)];

    int result;

    memset(t2, 0, sizeof(t2));
    memset(c2, 0, sizeof(c2));
    memset(p2, 0, sizeof(p2));

    AesGcmSetKey(&enc, k, sizeof(k));
    /* AES-GCM encrypt and decrypt both use AES encrypt internally */
    AesGcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv),
                                                 t2, sizeof(t2), a, sizeof(a));
    if (memcmp(c, c2, sizeof(c2)))
        return -68;
    if (memcmp(t, t2, sizeof(t2)))
        return -69;

    result = AesGcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv),
                                                 t2, sizeof(t2), a, sizeof(a));
    if (result != 0)
        return -70;
    if (memcmp(p, p2, sizeof(p2)))
        return -71;

    return 0;
}
#endif /* HAVE_AESGCM */

#ifdef HAVE_AESCCM
int aesccm_test(void)
{
    Aes enc;

    /* key */
    const byte k[] =
    {
        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
        0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf
    };

    /* nonce */
    const byte iv[] =
    {
        0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0,
        0xa1, 0xa2, 0xa3, 0xa4, 0xa5
    };

    /* plaintext */
    const byte p[] =
    {
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e
    };

    const byte a[] =
    {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
    };

    const byte c[] =
    {
        0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
        0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
        0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84
    };

    const byte t[] =
    {
        0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 
    };

    byte t2[sizeof(t)];
    byte p2[sizeof(p)];
    byte c2[sizeof(c)];

    int result;

    memset(t2, 0, sizeof(t2));
    memset(c2, 0, sizeof(c2));
    memset(p2, 0, sizeof(p2));

    AesCcmSetKey(&enc, k, sizeof(k));
    /* AES-CCM encrypt and decrypt both use AES encrypt internally */
    AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv),
                                                 t2, sizeof(t2), a, sizeof(a));
    if (memcmp(c, c2, sizeof(c2)))
        return -107;
    if (memcmp(t, t2, sizeof(t2)))
        return -108;

    result = AesCcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv),
                                                 t2, sizeof(t2), a, sizeof(a));
    if (result != 0)
        return -109;
    if (memcmp(p, p2, sizeof(p2)))
        return -110;

    /* Test the authentication failure */
    t2[0]++; /* Corrupt the authentication tag. */
    result = AesCcmDecrypt(&enc, p2, c, sizeof(p2), iv, sizeof(iv),
                                                 t2, sizeof(t2), a, sizeof(a));
    if (result == 0)
        return -111;

    /* Clear c2 to compare against p2. p2 should be set to zero in case of
     * authentication fail. */
    memset(c2, 0, sizeof(c2));
    if (memcmp(p2, c2, sizeof(p2)))
        return -112;

    return 0;
}
#endif /* HAVE_AESCCM */


#endif /* NO_AES */


#ifdef HAVE_CAMELLIA

enum {
    CAM_ECB_ENC, CAM_ECB_DEC, CAM_CBC_ENC, CAM_CBC_DEC
};

typedef struct {
    int type;
    const byte* plaintext;
    const byte* iv;
    const byte* ciphertext;
    const byte* key;
    word32 keySz;
    int errorCode;
} test_vector_t;

int camellia_test(void)
{
    /* Camellia ECB Test Plaintext */
    const byte pte[] = 
    {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
    };

    /* Camellia ECB Test Initialization Vector */
    const byte ive[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    /* Test 1: Camellia ECB 128-bit key */
    const byte k1[] =
    {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
    };
    const byte c1[] =
    {
        0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73,
        0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43
    };

    /* Test 2: Camellia ECB 192-bit key */
    const byte k2[] =
    {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
    };
    const byte c2[] =
    {
        0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8,
        0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9
    };

    /* Test 3: Camellia ECB 256-bit key */
    const byte k3[] =
    {
        0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
        0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
    };
    const byte c3[] =
    {
        0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c,
        0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09
    };

    /* Camellia CBC Test Plaintext */
    const byte ptc[] =
    {
        0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
        0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A 
    };

    /* Camellia CBC Test Initialization Vector */
    const byte ivc[] =
    {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 
    };

    /* Test 4: Camellia-CBC 128-bit key */
    const byte k4[] =
    {
        0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
        0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C 
    };
    const byte c4[] =
    {
        0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0,
        0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB 
    };

    /* Test 5: Camellia-CBC 192-bit key */
    const byte k5[] =
    {
        0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
        0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
        0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B 
    };
    const byte c5[] =
    {
        0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2,
        0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 
    };

    /* Test 6: CBC 256-bit key */
    const byte k6[] =
    {
        0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
        0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
        0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
        0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 
    };
    const byte c6[] =
    {
        0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A,
        0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA 
    };

    byte out[CAMELLIA_BLOCK_SIZE];
    Camellia cam;
    int i, testsSz;
    const test_vector_t testVectors[] =
    {
        {CAM_ECB_ENC, pte, ive, c1, k1, sizeof(k1), -114},
        {CAM_ECB_ENC, pte, ive, c2, k2, sizeof(k2), -115},
        {CAM_ECB_ENC, pte, ive, c3, k3, sizeof(k3), -116},
        {CAM_ECB_DEC, pte, ive, c1, k1, sizeof(k1), -117},
        {CAM_ECB_DEC, pte, ive, c2, k2, sizeof(k2), -118},
        {CAM_ECB_DEC, pte, ive, c3, k3, sizeof(k3), -119},
        {CAM_CBC_ENC, ptc, ivc, c4, k4, sizeof(k4), -120},
        {CAM_CBC_ENC, ptc, ivc, c5, k5, sizeof(k5), -121},
        {CAM_CBC_ENC, ptc, ivc, c6, k6, sizeof(k6), -122},
        {CAM_CBC_DEC, ptc, ivc, c4, k4, sizeof(k4), -123},
        {CAM_CBC_DEC, ptc, ivc, c5, k5, sizeof(k5), -124},
        {CAM_CBC_DEC, ptc, ivc, c6, k6, sizeof(k6), -125}
    };

    if ((sizeof(pte) != CAMELLIA_BLOCK_SIZE) ||
                                          (sizeof(ptc) != CAMELLIA_BLOCK_SIZE))
        return -113;

    testsSz = sizeof(testVectors)/sizeof(test_vector_t);
    for (i = 0; i < testsSz; i++) {
        CamelliaSetKey(&cam, testVectors[i].key, testVectors[i].keySz,
                                                             testVectors[i].iv);

        switch (testVectors[i].type) {
            case CAM_ECB_ENC:
                CamelliaEncryptDirect(&cam, out, testVectors[i].plaintext);
                if (memcmp(out, testVectors[i].ciphertext, CAMELLIA_BLOCK_SIZE))
                    return testVectors[i].errorCode;
                break;
            case CAM_ECB_DEC:
                CamelliaDecryptDirect(&cam, out, testVectors[i].ciphertext);
                if (memcmp(out, testVectors[i].plaintext, CAMELLIA_BLOCK_SIZE))
                    return testVectors[i].errorCode;
                break;
            case CAM_CBC_ENC:
                CamelliaCbcEncrypt(&cam, out, testVectors[i].plaintext,
                                                           CAMELLIA_BLOCK_SIZE);
                if (memcmp(out, testVectors[i].ciphertext, CAMELLIA_BLOCK_SIZE))
                    return testVectors[i].errorCode;
                break;
            case CAM_CBC_DEC:
                CamelliaCbcDecrypt(&cam, out, testVectors[i].ciphertext,
                                                           CAMELLIA_BLOCK_SIZE);
                if (memcmp(out, testVectors[i].plaintext, CAMELLIA_BLOCK_SIZE))
                    return testVectors[i].errorCode;
                break;
            default:
                break;
        }
    }

    /* Setting the IV and checking it was actually set. */
    CamelliaSetIV(&cam, ivc);
    if (XMEMCMP(cam.reg, ivc, CAMELLIA_BLOCK_SIZE))
        return -1;

    /* Setting the IV to NULL should leave the IV unchanged */
    if (CamelliaSetIV(&cam, NULL) != 0 ||
                                    XMEMCMP(cam.reg, ivc, CAMELLIA_BLOCK_SIZE))
        return -1;
    
    /* First parameter should never be null */
    if (CamelliaSetIV(NULL, NULL) == 0)
        return -1;

    /* First parameter should never be null, check it fails */
    if (CamelliaSetKey(NULL, k1, sizeof(k1), NULL) == 0)
        return -1;

    /* Key should have a size of 16, 24, or 32 */
    if (CamelliaSetKey(&cam, k1, 0, NULL) == 0)
        return -1;

    return 0;
}
#endif /* HAVE_CAMELLIA */


int random_test(void)
{
    RNG  rng;
    byte block[32];
    int ret;

#ifdef HAVE_CAVIUM
    ret = InitRngCavium(&rng, CAVIUM_DEV_ID);
    if (ret != 0) return -2007;
#endif
    ret = InitRng(&rng);
    if (ret != 0) return -39;

    RNG_GenerateBlock(&rng, block, sizeof(block));

    return 0;
}


#ifdef HAVE_NTRU

byte GetEntropy(ENTROPY_CMD cmd, byte* out);

byte GetEntropy(ENTROPY_CMD cmd, byte* out)
{
    static RNG rng;

    if (cmd == INIT) {
        int ret = InitRng(&rng);
        if (ret == 0)
            return 1;
        else
            return 0;
    }

    if (out == NULL)
        return 0;

    if (cmd == GET_BYTE_OF_ENTROPY) {
        RNG_GenerateBlock(&rng, out, 1);
        return 1;
    }

    if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
        *out = 1;
        return 1;
    }

    return 0;
}

#endif /* HAVE_NTRU */

#ifndef NO_RSA

#ifdef FREESCALE_MQX
    static const char* clientKey  = "a:\certs\\client-key.der";
    static const char* clientCert = "a:\certs\\client-cert.der";
    #ifdef CYASSL_CERT_GEN
        static const char* caKeyFile  = "a:\certs\\ca-key.der";
        static const char* caCertFile = "a:\certs\\ca-cert.pem";
    #endif
#elif !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
    static const char* clientKey  = "./certs/client-key.der";
    static const char* clientCert = "./certs/client-cert.der";
    #ifdef CYASSL_CERT_GEN
        static const char* caKeyFile  = "./certs/ca-key.der";
        static const char* caCertFile = "./certs/ca-cert.pem";
    #endif
#endif

#define FOURK_BUF 4096

int rsa_test(void)
{
    byte*   tmp;
    size_t bytes;
    RsaKey key;
    RNG    rng;
    word32 idx = 0;
    int    ret;
    byte   in[] = "Everyone gets Friday off.";
    word32 inLen = (word32)strlen((char*)in);
    byte   out[256];
    byte   plain[256];
#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
    FILE*  file, * file2;
#endif
#ifdef CYASSL_TEST_CERT
    DecodedCert cert;
#endif

    tmp = (byte*)malloc(FOURK_BUF);
    if (tmp == NULL)
        return -40;

#ifdef USE_CERT_BUFFERS_1024
    XMEMCPY(tmp, client_key_der_1024, sizeof(client_key_der_1024));
    bytes = sizeof(client_key_der_1024);
#elif defined(USE_CERT_BUFFERS_2048)
    XMEMCPY(tmp, client_key_der_2048, sizeof(client_key_der_2048));
    bytes = sizeof(client_key_der_2048);
#else
    file = fopen(clientKey, "rb");

    if (!file)
        err_sys("can't open ./certs/client-key.der, "
                "Please run from CyaSSL home dir", -40);

    bytes = fread(tmp, 1, FOURK_BUF, file);
    fclose(file);
#endif /* USE_CERT_BUFFERS */
 
#ifdef HAVE_CAVIUM
    RsaInitCavium(&key, CAVIUM_DEV_ID);
#endif 
    InitRsaKey(&key, 0);  
    ret = RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes);
    if (ret != 0) return -41;

    ret = InitRng(&rng);
    if (ret != 0) return -42;

    ret = RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng);
    if (ret < 0) return -43;

    ret = RsaPrivateDecrypt(out, ret, plain, sizeof(plain), &key);
    if (ret < 0) return -44;

    if (memcmp(plain, in, inLen)) return -45;

    ret = RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng);
    if (ret < 0) return -46;

    memset(plain, 0, sizeof(plain));
    ret = RsaSSL_Verify(out, ret, plain, sizeof(plain), &key);
    if (ret < 0) return -47;

    if (memcmp(plain, in, ret)) return -48;

#ifdef USE_CERT_BUFFERS_1024
    XMEMCPY(tmp, client_cert_der_1024, sizeof(client_cert_der_1024));
    bytes = sizeof(client_cert_der_1024);
#elif defined(USE_CERT_BUFFERS_2048)
    XMEMCPY(tmp, client_cert_der_2048, sizeof(client_cert_der_2048));
    bytes = sizeof(client_cert_der_2048);
#else
    file2 = fopen(clientCert, "rb");
    if (!file2)
        return -49;

    bytes = fread(tmp, 1, FOURK_BUF, file2);
    fclose(file2);
#endif

#ifdef CYASSL_TEST_CERT
    InitDecodedCert(&cert, tmp, (word32)bytes, 0);

    ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0);
    if (ret != 0) return -491;

    FreeDecodedCert(&cert);
#else
    (void)bytes;
#endif


#ifdef CYASSL_KEY_GEN
    {
        byte*  der;
        byte*  pem;
        int    derSz = 0;
        int    pemSz = 0;
        RsaKey derIn;
        RsaKey genKey;
        FILE* keyFile;
        FILE* pemFile;

        InitRsaKey(&genKey, 0);
        ret = MakeRsaKey(&genKey, 1024, 65537, &rng);
        if (ret != 0)
            return -301;

        der = (byte*)malloc(FOURK_BUF);
        if (der == NULL)
            return -307;
        pem = (byte*)malloc(FOURK_BUF);
        if (pem == NULL)
            return -308;

        derSz = RsaKeyToDer(&genKey, der, FOURK_BUF);
        if (derSz < 0)
            return -302;

        //keyFile = fopen("./key.der", "wb");
        //if (!keyFile)
            //return -303;
        //ret = (int)fwrite(der, derSz, 1, keyFile);
        //fclose(keyFile);

        pemSz = DerToPem(der, derSz, pem, FOURK_BUF, PRIVATEKEY_TYPE);
        if (pemSz < 0)
            return -304;

        //pemFile = fopen("./key.pem", "wb");
        //if (!pemFile) 
            //return -305;
        //ret = (int)fwrite(pem, pemSz, 1, pemFile);
        //fclose(pemFile);

        InitRsaKey(&derIn, 0);
        idx = 0;
        ret = RsaPrivateKeyDecode(der, &idx, &derIn, derSz);
        if (ret != 0)
            return -306;

        FreeRsaKey(&derIn);
        FreeRsaKey(&genKey);
        free(pem);
        free(der);
    }
#endif /* CYASSL_KEY_GEN */


#ifdef CYASSL_CERT_GEN
    /* self signed */
    {
        Cert        myCert;
        byte*       derCert;
        byte*       pem;
        FILE*       derFile;
        FILE*       pemFile;
        int         certSz;
        int         pemSz;
#ifdef CYASSL_TEST_CERT
        DecodedCert decode;
#endif

        derCert = (byte*)malloc(FOURK_BUF);
        if (derCert == NULL)
            return -309;
        pem = (byte*)malloc(FOURK_BUF);
        if (pem == NULL)
            return -310;

        InitCert(&myCert);

        strncpy(myCert.subject.country, "US", CTC_NAME_SIZE);
        strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE);
        strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE);
        strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE);
        strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE);
        strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE);
        strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE);
        myCert.isCA    = 1;
        myCert.sigType = CTC_SHA256wRSA;

        certSz = MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng); 
        if (certSz < 0)
            return -401;

#ifdef CYASSL_TEST_CERT
        InitDecodedCert(&decode, derCert, certSz, 0);
        ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0);
        if (ret != 0)
            return -402;
        FreeDecodedCert(&decode);
#endif
        derFile = fopen("./cert.der", "wb");
        if (!derFile)
            return -403;
        ret = (int)fwrite(derCert, certSz, 1, derFile);
        fclose(derFile);

        pemSz = DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE);
        if (pemSz < 0)
            return -404;

        pemFile = fopen("./cert.pem", "wb");
        if (!pemFile)
            return -405;
        ret = (int)fwrite(pem, pemSz, 1, pemFile);
        fclose(pemFile);
        free(pem);
        free(derCert);
    }
    /* CA style */
    {
        RsaKey      caKey;
        Cert        myCert;
        byte*       derCert;
        byte*       pem;
        FILE*       derFile;
        FILE*       pemFile;
        int         certSz;
        int         pemSz;
        size_t      bytes3;
        word32      idx3 = 0;
#ifdef CYASSL_TEST_CERT
        DecodedCert decode;
#endif

        derCert = (byte*)malloc(FOURK_BUF);
        if (derCert == NULL)
            return -311;
        pem = (byte*)malloc(FOURK_BUF);
        if (pem == NULL)
            return -312;

        FILE* file3 = fopen(caKeyFile, "rb");

        if (!file3)
            return -412;

        bytes3 = fread(tmp, 1, FOURK_BUF, file3);
        fclose(file3);
  
        InitRsaKey(&caKey, 0);  
        ret = RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3);
        if (ret != 0) return -413;

        InitCert(&myCert);

        strncpy(myCert.subject.country, "US", CTC_NAME_SIZE);
        strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE);
        strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE);
        strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE);
        strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE);
        strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE);
        strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE);

        ret = SetIssuer(&myCert, caCertFile);
        if (ret < 0)
            return -405;

        certSz = MakeCert(&myCert, derCert, FOURK_BUF, &key, &rng); 
        if (certSz < 0)
            return -407;

        certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, &rng);
        if (certSz < 0)
            return -408;


#ifdef CYASSL_TEST_CERT
        InitDecodedCert(&decode, derCert, certSz, 0);
        ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0);
        if (ret != 0)
            return -409;
        FreeDecodedCert(&decode);
#endif

        derFile = fopen("./othercert.der", "wb");
        if (!derFile)
            return -410;
        ret = (int)fwrite(derCert, certSz, 1, derFile);
        fclose(derFile);

        pemSz = DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE);
        if (pemSz < 0)
            return -411;

        pemFile = fopen("./othercert.pem", "wb");
        if (!pemFile)
            return -412;
        ret = (int)fwrite(pem, pemSz, 1, pemFile);
        fclose(pemFile);
        free(pem);
        free(derCert);
        FreeRsaKey(&caKey);
    }
#ifdef HAVE_NTRU
    {
        RsaKey      caKey;
        Cert        myCert;
        byte*       derCert;
        byte*       pem;
        FILE*       derFile;
        FILE*       pemFile;
        FILE*       caFile;
        FILE*       ntruPrivFile;
        int         certSz;
        int         pemSz;
        size_t      bytes;
        word32      idx = 0;
#ifdef CYASSL_TEST_CERT
        DecodedCert decode;
#endif
        derCert = (byte*)malloc(FOURK_BUF);
        if (derCert == NULL)
            return -311;
        pem = (byte*)malloc(FOURK_BUF);
        if (pem == NULL)
            return -312;

        byte   public_key[557];          /* sized for EES401EP2 */
        word16 public_key_len;           /* no. of octets in public key */
        byte   private_key[607];         /* sized for EES401EP2 */
        word16 private_key_len;          /* no. of octets in private key */
        DRBG_HANDLE drbg;
        static uint8_t const pers_str[] = {
                'C', 'y', 'a', 'S', 'S', 'L', ' ', 't', 'e', 's', 't'
        };
        word32 rc = crypto_drbg_instantiate(112, pers_str, sizeof(pers_str),
                                            GetEntropy, &drbg);
        if (rc != DRBG_OK)
            return -450;

        rc = crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len,
                                        NULL, &private_key_len, NULL);
        if (rc != NTRU_OK)
            return -451;

        rc = crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len,
                                     public_key, &private_key_len, private_key);
        crypto_drbg_uninstantiate(drbg);

        if (rc != NTRU_OK)
            return -452;

        caFile = fopen(caKeyFile, "rb");

        if (!caFile)
            return -453;

        bytes = fread(tmp, 1, FOURK_BUF, caFile);
        fclose(caFile);
  
        InitRsaKey(&caKey, 0);  
        ret = RsaPrivateKeyDecode(tmp, &idx, &caKey, (word32)bytes);
        if (ret != 0) return -454;

        InitCert(&myCert);

        strncpy(myCert.subject.country, "US", CTC_NAME_SIZE);
        strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE);
        strncpy(myCert.subject.locality, "Portland", CTC_NAME_SIZE);
        strncpy(myCert.subject.org, "yaSSL", CTC_NAME_SIZE);
        strncpy(myCert.subject.unit, "Development", CTC_NAME_SIZE);
        strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE);
        strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE);

        ret = SetIssuer(&myCert, caCertFile);
        if (ret < 0)
            return -455;

        certSz = MakeNtruCert(&myCert, derCert, FOURK_BUF, public_key,
                              public_key_len, &rng); 
        if (certSz < 0)
            return -456;

        certSz = SignCert(&myCert, derCert, FOURK_BUF, &caKey, &rng);
        if (certSz < 0)
            return -457;


#ifdef CYASSL_TEST_CERT
        InitDecodedCert(&decode, derCert, certSz, 0);
        ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0);
        if (ret != 0)
            return -458;
        FreeDecodedCert(&decode);
#endif
        derFile = fopen("./ntru-cert.der", "wb");
        if (!derFile)
            return -459;
        ret = fwrite(derCert, certSz, 1, derFile);
        fclose(derFile);

        pemSz = DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE);
        if (pemSz < 0)
            return -460;

        pemFile = fopen("./ntru-cert.pem", "wb");
        if (!pemFile)
            return -461;
        ret = fwrite(pem, pemSz, 1, pemFile);
        fclose(pemFile);

        ntruPrivFile = fopen("./ntru-key.raw", "wb");
        if (!ntruPrivFile)
            return -462;
        ret = fwrite(private_key, private_key_len, 1, ntruPrivFile);
        fclose(ntruPrivFile);
        free(pem);
        free(derCert);
        FreeRsaKey(&caKey);
    }
#endif /* HAVE_NTRU */
#endif /* CYASSL_CERT_GEN */

    FreeRsaKey(&key);
#ifdef HAVE_CAVIUM
    RsaFreeCavium(&key);
#endif 
    free(tmp);

    return 0;
}

#endif


#ifndef NO_DH

#ifdef FREESCALE_MQX
    static const char* dhKey = "a:\certs\\dh2048.der";
#elif !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
    static const char* dhKey = "./certs/dh2048.der";
#endif

int dh_test(void)
{
    int    ret;
    word32 bytes;
    word32 idx = 0, privSz, pubSz, privSz2, pubSz2, agreeSz, agreeSz2;
    byte   tmp[1024];
    byte   priv[256];
    byte   pub[256];
    byte   priv2[256];
    byte   pub2[256];
    byte   agree[256];
    byte   agree2[256];
    DhKey  key;
    DhKey  key2;
    RNG    rng;
#ifdef USE_CERT_BUFFERS_1024
    XMEMCPY(tmp, dh_key_der_1024, sizeof(dh_key_der_1024));
    bytes = sizeof(dh_key_der_1024);
#elif defined(USE_CERT_BUFFERS_2048)
    XMEMCPY(tmp, dh_key_der_2048, sizeof(dh_key_der_2048));
    bytes = sizeof(dh_key_der_2048);
#else
    FILE*  file = fopen(dhKey, "rb");

    if (!file)
        return -50;

    bytes = (word32) fread(tmp, 1, sizeof(tmp), file);
    fclose(file);
#endif /* USE_CERT_BUFFERS */

    InitDhKey(&key);
    InitDhKey(&key2);
    ret = DhKeyDecode(tmp, &idx, &key, bytes);
    if (ret != 0)
        return -51;

    idx = 0;
    ret = DhKeyDecode(tmp, &idx, &key2, bytes);
    if (ret != 0)
        return -52;

    ret = InitRng(&rng);
    if (ret != 0)
        return -53;

    ret =  DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz);
    ret += DhGenerateKeyPair(&key2, &rng, priv2, &privSz2, pub2, &pubSz2);
    if (ret != 0)
        return -54;

    ret =  DhAgree(&key, agree, &agreeSz, priv, privSz, pub2, pubSz2);
    ret += DhAgree(&key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz);
    if (ret != 0)
        return -55;

    if (memcmp(agree, agree2, agreeSz))
        return -56;

    FreeDhKey(&key);
    FreeDhKey(&key2);

    return 0;
}

#endif /* NO_DH */


#ifndef NO_DSA

#ifdef FREESCALE_MQX
    static const char* dsaKey = "a:\certs\\dsa2048.der";
#elif !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048)
    static const char* dsaKey = "./certs/dsa2048.der";
#endif

int dsa_test(void)
{
    int    ret, answer;
    word32 bytes;
    word32 idx = 0;
    byte   tmp[1024];
    DsaKey key;
    RNG    rng;
    Sha    sha;
    byte   hash[SHA_DIGEST_SIZE];
    byte   signature[40];
#ifdef USE_CERT_BUFFERS_1024
    XMEMCPY(tmp, dsa_key_der_1024, sizeof(dsa_key_der_1024));
    bytes = sizeof(dsa_key_der_1024);
#elif defined(USE_CERT_BUFFERS_2048)
    XMEMCPY(tmp, dsa_key_der_2048, sizeof(dsa_key_der_2048));
    bytes = sizeof(dsa_key_der_2048);
#else
    FILE*  file = fopen(dsaKey, "rb");

    if (!file)
        return -60;

    bytes = (word32) fread(tmp, 1, sizeof(tmp), file);
    fclose(file);
#endif /* USE_CERT_BUFFERS */
  
    InitSha(&sha);
    ShaUpdate(&sha, tmp, bytes);
    ShaFinal(&sha, hash);

    InitDsaKey(&key);
    ret = DsaPrivateKeyDecode(tmp, &idx, &key, bytes);
    if (ret != 0) return -61;

    ret = InitRng(&rng);
    if (ret != 0) return -62;

    ret = DsaSign(hash, signature, &key, &rng);
    if (ret != 0) return -63;

    ret = DsaVerify(hash, signature, &key, &answer);
    if (ret != 0) return -64;
    if (answer != 1) return -65;
    
    FreeDsaKey(&key);
    
    return 0;
}

#endif /* NO_DSA */


#ifdef OPENSSL_EXTRA

int openssl_test(void)
{
    EVP_MD_CTX md_ctx;
    testVector a, b, c, d, e, f;
    byte       hash[SHA_DIGEST_SIZE*4];  /* max size */

    (void)e;
    (void)f;

    a.input  = "1234567890123456789012345678901234567890123456789012345678"
               "9012345678901234567890";
    a.output = "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6"
               "\x7a";
    a.inLen  = strlen(a.input);
    a.outLen = MD5_DIGEST_SIZE;

    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit(&md_ctx, EVP_md5());

    EVP_DigestUpdate(&md_ctx, a.input, a.inLen);
    EVP_DigestFinal(&md_ctx, hash, 0);

    if (memcmp(hash, a.output, MD5_DIGEST_SIZE) != 0)
        return -71;

    b.input  = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
               "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
               "aaaaaaaaaa";
    b.output = "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7"
               "\x53\x99\x5E\x26\xA0";
    b.inLen  = strlen(b.input);
    b.outLen = SHA_DIGEST_SIZE;

    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit(&md_ctx, EVP_sha1());

    EVP_DigestUpdate(&md_ctx, b.input, b.inLen);
    EVP_DigestFinal(&md_ctx, hash, 0);

    if (memcmp(hash, b.output, SHA_DIGEST_SIZE) != 0)
        return -72;


    d.input  = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
    d.output = "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60"
               "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB"
               "\x06\xC1";
    d.inLen  = strlen(d.input);
    d.outLen = SHA256_DIGEST_SIZE;

    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit(&md_ctx, EVP_sha256());

    EVP_DigestUpdate(&md_ctx, d.input, d.inLen);
    EVP_DigestFinal(&md_ctx, hash, 0);

    if (memcmp(hash, d.output, SHA256_DIGEST_SIZE) != 0)
        return -78;

#ifdef CYASSL_SHA384

    e.input  = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi"
               "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
    e.output = "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b"
               "\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0"
               "\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91"
               "\x74\x60\x39";    
    e.inLen  = strlen(e.input);
    e.outLen = SHA384_DIGEST_SIZE;

    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit(&md_ctx, EVP_sha384());

    EVP_DigestUpdate(&md_ctx, e.input, e.inLen);
    EVP_DigestFinal(&md_ctx, hash, 0);

    if (memcmp(hash, e.output, SHA384_DIGEST_SIZE) != 0)
        return -79;

#endif /* CYASSL_SHA384 */


#ifdef CYASSL_SHA512

    f.input  = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi"
               "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
    f.output = "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14"
               "\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88"
               "\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4"
               "\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b"
               "\x87\x4b\xe9\x09"; 
    f.inLen  = strlen(f.input);
    f.outLen = SHA512_DIGEST_SIZE; 

    EVP_MD_CTX_init(&md_ctx);
    EVP_DigestInit(&md_ctx, EVP_sha512());

    EVP_DigestUpdate(&md_ctx, f.input, f.inLen);
    EVP_DigestFinal(&md_ctx, hash, 0);

    if (memcmp(hash, f.output, SHA512_DIGEST_SIZE) != 0)
        return -80;

#endif /* CYASSL_SHA512 */


    if (RAND_bytes(hash, sizeof(hash)) != 1)
        return -73;
            
    c.input  = "what do ya want for nothing?";
    c.output = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7"
               "\x38";
    c.inLen  = strlen(c.input);
    c.outLen = MD5_DIGEST_SIZE;

    HMAC(EVP_md5(), "Jefe", 4, (byte*)c.input, (int)c.inLen, hash, 0);

    if (memcmp(hash, c.output, MD5_DIGEST_SIZE) != 0)
        return -74;

    { /* des test */
    const byte vector[] = { /* "now is the time for all " w/o trailing 0 */
        0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
        0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
        0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
    };

    byte plain[24];
    byte cipher[24];

    const_DES_cblock key = 
    {
        0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef
    };

    DES_cblock iv = 
    {
        0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef
    };

    DES_key_schedule sched;

    const byte verify[] = 
    {
        0x8b,0x7c,0x52,0xb0,0x01,0x2b,0x6c,0xb8,
        0x4f,0x0f,0xeb,0xf3,0xfb,0x5f,0x86,0x73,
        0x15,0x85,0xb3,0x22,0x4b,0x86,0x2b,0x4b
    };

    DES_key_sched(&key, &sched);

    DES_cbc_encrypt(vector, cipher, sizeof(vector), &sched, &iv, DES_ENCRYPT);
    DES_cbc_encrypt(cipher, plain, sizeof(vector), &sched, &iv, DES_DECRYPT);

    if (memcmp(plain, vector, sizeof(vector)) != 0)
        return -75;

    if (memcmp(cipher, verify, sizeof(verify)) != 0)
        return -76;

        /* test changing iv */
    DES_ncbc_encrypt(vector, cipher, 8, &sched, &iv, DES_ENCRYPT);
    DES_ncbc_encrypt(vector + 8, cipher + 8, 16, &sched, &iv, DES_ENCRYPT);

    if (memcmp(cipher, verify, sizeof(verify)) != 0)
        return -77;

    }  /* end des test */

    {  /* evp_cipher test */
        EVP_CIPHER_CTX ctx;


        const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */
            0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74,
            0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20,
            0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20
        };

        const byte verify[] = 
        {
            0x95,0x94,0x92,0x57,0x5f,0x42,0x81,0x53,
            0x2c,0xcc,0x9d,0x46,0x77,0xa2,0x33,0xcb
        };

        byte key[] = "0123456789abcdef   ";  /* align */
        byte iv[]  = "1234567890abcdef   ";  /* align */

        byte cipher[AES_BLOCK_SIZE * 4];
        byte plain [AES_BLOCK_SIZE * 4];

        EVP_CIPHER_CTX_init(&ctx);
        if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0)
            return -81;

        if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0)
            return -82;

        if (memcmp(cipher, verify, AES_BLOCK_SIZE))
            return -83;

        EVP_CIPHER_CTX_init(&ctx);
        if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0)
            return -84;

        if (EVP_Cipher(&ctx, plain, cipher, 16) == 0)
            return -85;

        if (memcmp(plain, msg, AES_BLOCK_SIZE))
            return -86;


    }  /* end evp_cipher test */

    return 0;
}

#endif /* OPENSSL_EXTRA */


#ifndef NO_PWDBASED

int pkcs12_test(void)
{
    const byte passwd[] = { 0x00, 0x73, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x67,
                            0x00, 0x00 }; 
    const byte salt[] =   { 0x0a, 0x58, 0xCF, 0x64, 0x53, 0x0d, 0x82, 0x3f };

    const byte passwd2[] = { 0x00, 0x71, 0x00, 0x75, 0x00, 0x65, 0x00, 0x65,
                             0x00, 0x67, 0x00, 0x00 }; 
    const byte salt2[] =   { 0x16, 0x82, 0xC0, 0xfC, 0x5b, 0x3f, 0x7e, 0xc5 };
    byte  derived[64];

    const byte verify[] = {
        0x8A, 0xAA, 0xE6, 0x29, 0x7B, 0x6C, 0xB0, 0x46,
        0x42, 0xAB, 0x5B, 0x07, 0x78, 0x51, 0x28, 0x4E,
        0xB7, 0x12, 0x8F, 0x1A, 0x2A, 0x7F, 0xBC, 0xA3
    };

    const byte verify2[] = {
        0x48, 0x3D, 0xD6, 0xE9, 0x19, 0xD7, 0xDE, 0x2E,
        0x8E, 0x64, 0x8B, 0xA8, 0xF8, 0x62, 0xF3, 0xFB,
        0xFB, 0xDC, 0x2B, 0xCB, 0x2C, 0x02, 0x95, 0x7F
    };

    int id         =  1;
    int kLen       = 24;
    int iterations =  1;
    int ret = PKCS12_PBKDF(derived, passwd, sizeof(passwd), salt, 8, iterations,
                           kLen, SHA, id);

    if (ret < 0)
        return -103;

    if ( (ret = memcmp(derived, verify, kLen)) != 0)
        return -104;

    iterations = 1000;
    ret = PKCS12_PBKDF(derived, passwd2, sizeof(passwd2), salt2, 8, iterations, 
                       kLen, SHA, id);
    if (ret < 0)
        return -105;

    if ( (ret = memcmp(derived, verify2, 24)) != 0)
        return -106;

    return 0;
}


int pbkdf2_test(void)
{
    char passwd[] = "password";
    const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06 };
    int   iterations = 2048;
    int   kLen = 24;
    byte  derived[64];

    const byte verify[] = {
        0xBF, 0xDE, 0x6B, 0xE9, 0x4D, 0xF7, 0xE1, 0x1D, 0xD4, 0x09, 0xBC, 0xE2,
        0x0A, 0x02, 0x55, 0xEC, 0x32, 0x7C, 0xB9, 0x36, 0xFF, 0xE9, 0x36, 0x43

    };

    PBKDF2(derived, (byte*)passwd, (int)strlen(passwd), salt, 8, iterations,
           kLen, SHA);

    if (memcmp(derived, verify, sizeof(verify)) != 0)
        return -102;

    return 0;
}


int pbkdf1_test(void)
{
    char passwd[] = "password";
    const byte salt[] = { 0x78, 0x57, 0x8E, 0x5a, 0x5d, 0x63, 0xcb, 0x06 };
    int   iterations = 1000;
    int   kLen = 16;
    byte  derived[16];

    const byte verify[] = {
        0xDC, 0x19, 0x84, 0x7E, 0x05, 0xC6, 0x4D, 0x2F, 0xAF, 0x10, 0xEB, 0xFB,
        0x4A, 0x3D, 0x2A, 0x20
    };

    PBKDF1(derived, (byte*)passwd, (int)strlen(passwd), salt, 8, iterations,
           kLen, SHA);

    if (memcmp(derived, verify, sizeof(verify)) != 0)
        return -101;

    return 0;
}


int pwdbased_test(void)
{
   int ret =  pbkdf1_test();
   ret += pbkdf2_test();

   return ret + pkcs12_test();
}

#endif /* NO_PWDBASED */


#ifdef HAVE_ECC

int ecc_test(void)
{
    RNG     rng;
    byte    sharedA[1024];
    byte    sharedB[1024];
    byte    sig[1024];
    byte    digest[20];
    byte    exportBuf[1024];
    word32  x, y;
    int     i, verify, ret;
    ecc_key userA, userB, pubKey;

    ret = InitRng(&rng);
    if (ret != 0)
        return -1001;

    ecc_init(&userA);
    ecc_init(&userB);
    ecc_init(&pubKey);

    ret = ecc_make_key(&rng, 32, &userA);
    ret = ecc_make_key(&rng, 32, &userB);

    if (ret != 0)
        return -1002;

    x = sizeof(sharedA);
    ret = ecc_shared_secret(&userA, &userB, sharedA, &x);
   
    y = sizeof(sharedB);
    ret = ecc_shared_secret(&userB, &userA, sharedB, &y);
    
    if (ret != 0)
        return -1003;

    if (y != x)
        return -1004;

    if (memcmp(sharedA, sharedB, x))
        return -1005;

    x = sizeof(exportBuf);
    ret = ecc_export_x963(&userA, exportBuf, &x);
    if (ret != 0)
        return -1006;

    ret = ecc_import_x963(exportBuf, x, &pubKey);

    if (ret != 0) 
        return -1007;

    y = sizeof(sharedB);
    ret = ecc_shared_secret(&userB, &pubKey, sharedB, &y);
   
    if (ret != 0)
        return -1008;

    if (memcmp(sharedA, sharedB, y))
        return -1010;

    /* test DSA sign hash */
    for (i = 0; i < (int)sizeof(digest); i++)
        digest[i] = i;

    x = sizeof(sig);
    ret = ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &userA);
    
    verify = 0;
    ret = ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &userA);

    if (ret != 0)
        return -1011;

    if (verify != 1)
        return -1012;

    ecc_free(&pubKey);
    ecc_free(&userB);
    ecc_free(&userA);

    return 0;
}

#endif /* HAVE_ECC */

#ifdef HAVE_LIBZ

const byte sample_text[] =
    "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\r\n"
    "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\r\n"
    "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\r\n"
    "plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\r\n"
    "selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\r\n"
    "small batch meggings kogi dolore food truck bespoke gastropub.\r\n"
    "\r\n"
    "Terry richardson adipisicing actually typewriter tumblr, twee whatever\r\n"
    "four loko you probably haven't heard of them high life. Messenger bag\r\n"
    "whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\r\n"
    "et, banksy ullamco messenger bag umami pariatur direct trade forage.\r\n"
    "Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\r\n"
    "food truck next level, tousled irony non semiotics PBR ethical anim cred\r\n"
    "readymade. Mumblecore brunch lomo odd future, portland organic terry\r\n"
    "richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\r\n"
    "mixtape polaroid, pork belly readymade organic cray typewriter helvetica\r\n"
    "four loko whatever street art yr farm-to-table.\r\n"
    "\r\n"
    "Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\r\n"
    "pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\r\n"
    "et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\r\n"
    "nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\r\n"
    "seitan fingerstache kale chips. Terry richardson artisan williamsburg,\r\n"
    "eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\r\n"
    "readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\r\n"
    "ethnic art party qui letterpress nisi proident jean shorts mlkshk\r\n"
    "locavore.\r\n"
    "\r\n"
    "Narwhal flexitarian letterpress, do gluten-free voluptate next level\r\n"
    "banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\r\n"
    "cillum pickled velit, YOLO officia you probably haven't heard of them\r\n"
    "trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\r\n"
    "small batch american apparel. Put a bird on it cosby sweater before they\r\n"
    "sold out pork belly kogi hella. Street art mollit sustainable polaroid,\r\n"
    "DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\r\n"
    "Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\r\n"
    "excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\r\n"
    "neutra PBR selvage.\r\n"
    "\r\n"
    "Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\r\n"
    "next level jean shorts exercitation. Hashtag keytar whatever, nihil\r\n"
    "authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\r\n"
    "wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\r\n"
    "tattooed. Labore high life commodo, meggings raw denim fingerstache pug\r\n"
    "trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\r\n"
    "incididunt flannel sustainable helvetica pork belly pug banksy you\r\n"
    "probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\r\n"
    "mollit magna, sriracha sartorial helvetica.\r\n"
    "\r\n"
    "Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\r\n"
    "ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\r\n"
    "of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\r\n"
    "reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\r\n"
    "skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\r\n"
    "organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\r\n"
    "Veniam sunt food truck leggings, sint vinyl fap.\r\n"
    "\r\n"
    "Hella dolore pork belly, truffaut carles you probably haven't heard of\r\n"
    "them PBR helvetica in sapiente. Fashion axe ugh bushwick american\r\n"
    "apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\r\n"
    "flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\r\n"
    "letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\r\n"
    "Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\r\n"
    "delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\r\n"
    "magna pop-up literally. Swag thundercats ennui shoreditch vegan\r\n"
    "pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\r\n"
    "\r\n"
    "Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\r\n"
    "meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\r\n"
    "dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\r\n"
    "locavore kale chips. Sriracha swag thundercats, chillwave disrupt\r\n"
    "tousled beard mollit mustache leggings portland next level. Nihil esse\r\n"
    "est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\r\n"
    "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\r\n"
    "bag dolor terry richardson sapiente.\r\n";


int compress_test(void)
{
    int ret = 0;
    word32 dSz = sizeof(sample_text);
    word32 cSz = (dSz + (word32)(dSz * 0.001) + 12);
    byte *c = NULL;
    byte *d = NULL;

    c = calloc(cSz, sizeof(byte));
    d = calloc(dSz, sizeof(byte));

    if (c == NULL || d == NULL)
        ret = -300;

    if (ret == 0 && (ret = Compress(c, cSz, sample_text, dSz, 0)) < 0)
        ret = -301;

    if (ret > 0) {
        cSz = (word32)ret;
        ret = 0;
    }

    if (ret == 0 && DeCompress(d, dSz, c, cSz) != (int)dSz)
        ret = -302;

    if (ret == 0 && memcmp(d, sample_text, dSz))
        ret = -303;
    
    if (c) free(c);
    if (d) free(d);

    return ret;
}

#endif /* HAVE_LIBZ */


#endif





#ifdef BENCHMARK




#ifndef NO_MD5
void bench_md5(void)
{
    Md5    hash;
    byte   digest[MD5_DIGEST_SIZE];
    double start, total, persec;
    int    i;

    InitMd5(&hash);
    start = (double)TC1_Get_us();

    for(i = 0; i < numBlocks; i++)
        Md5Update(&hash, plain, sizeof(plain));

    Md5Final(&hash, digest);

    total = (double)TC1_Get_us() - start;
    persec = 1 / total * numBlocks;
#ifdef BENCH_EMBEDDED
    /* since using kB, convert to MB/s */
    persec = persec / 1024;
#endif

    printk("MD5      %d %s took %d miliseconds\r\r\n", numBlocks,blockType, (int)total);
}
#endif /* NO_MD5 */



#ifndef NO_RABBIT
void bench_rabbit(void)
{
	Rabbit  enc;
	double start, total, persec;
	int    i;
	
	RabbitSetKey(&enc, key, iv);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	RabbitProcess(&enc, cipher, plain, sizeof(plain));

	total = (double)TC1_Get_us() - start;
	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	printk("RABBIT   %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
}
#endif /* NO_RABBIT */


#if !defined(NO_RSA) || !defined(NO_DH) \
|| defined(CYASSL_KEYGEN) || defined(HAVE_ECC)
RNG rng;
#endif




#ifndef NO_RSA
void bench_rsa(void)
{
	int    i;
	int    ret;
	byte   tmp[3072];
	size_t bytes;
	word32 idx = 0;

	byte      message[] = "Everyone gets Friday off.";
	byte      enc[512];  /* for up to 4096 bit */
	const int len = (int)strlen((char*)message);
	double    start, total, each, milliEach;
	
	RsaKey rsaKey;
	int    rsaKeySz = 2048; /* used in printk */

	#ifdef USE_CERT_BUFFERS_1024
	XMEMCPY(tmp, rsa_key_der_1024, sizeof(rsa_key_der_1024));
	bytes = sizeof(rsa_key_der_1024);
	rsaKeySz = 1024;
	#elif defined(USE_CERT_BUFFERS_2048)
	XMEMCPY(tmp, rsa_key_der_2048, sizeof(rsa_key_der_2048));
	bytes = sizeof(rsa_key_der_2048);
	#else
	FILE*  file = fopen("./certs/rsa2048.der", "rb");

	if (!file) {
		printf("can't find ./certs/rsa2048.der, "
		"Please run from CyaSSL home dir\n");
		return;
	}
	
	bytes = fread(tmp, 1, sizeof(tmp), file);
	fclose(file);
	#endif /* USE_CERT_BUFFERS */

	#ifdef HAVE_CAVIUM
	if (RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0)
	printf("RSA init cavium failed\n");
	#endif
	ret = InitRng(&rng);
	if (ret < 0) {
		printf("InitRNG failed\n");
		return;
	}
	InitRsaKey(&rsaKey, 0);
	ret = RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes);
	
	start = (double)TC1_Get_us();

	for (i = 0; i < times; i++)
	ret = RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng);

	total = (double)TC1_Get_us() - start;
	each  = total / times;   /* per second   */
	milliEach = each * 1000; /* milliseconds */

	printk("RSA %d encryption took %d milliseconds, avg over %d"
	" iterations\r\r\n", rsaKeySz, (int)milliEach/1000, times);

	if (ret < 0) {
		printf("Rsa Public Encrypt failed\n");
		return;
	}

	start = (double)TC1_Get_us();

	for (i = 0; i < times; i++) {
		byte  out[512];  /* for up to 4096 bit */
		RsaPrivateDecrypt(enc, (word32)ret, out, sizeof(out), &rsaKey);
	}

	total = (double)TC1_Get_us() - start;
	each  = total / times;   /* per second   */
	milliEach = each * 1000; /* milliseconds */

	printk("RSA %d decryption took %d milliseconds, avg over %d"
	" iterations\r\r\n", rsaKeySz, (int)milliEach/1000, times);

	FreeRsaKey(&rsaKey);
	#ifdef HAVE_CAVIUM
	RsaFreeCavium(&rsaKey);
	#endif
}
#endif




#ifndef NO_AES
void bench_aes(int show)
{
	Aes    enc;
	double start, total, persec;
	int    i;

	#ifdef HAVE_CAVIUM
	if (AesInitCavium(&enc, CAVIUM_DEV_ID) != 0)
	printf("aes init cavium failed\n");
	#endif

	AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	AesCbcEncrypt(&enc, plain, cipher, sizeof(plain));

	total = (double)TC1_Get_us() - start;

	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	if (show)
	printk("AES      %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
	#ifdef HAVE_CAVIUM
	AesFreeCavium(&enc);
	#endif
}
#endif


byte additional[13];
byte tag[16];


#ifdef HAVE_AESGCM
void bench_aesgcm(void)
{
	Aes    enc;
	double start, total, persec;
	int    i;

	AesGcmSetKey(&enc, key, 16);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12,
	tag, 16, additional, 13);

	total = (double)TC1_Get_us() - start;

	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	printk("AES-GCM  %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
}
#endif


#ifdef HAVE_AESCCM
void bench_aesccm(void)
{
	Aes    enc;
	double start, total, persec;
	int    i;

	AesCcmSetKey(&enc, key, 16);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12,
	tag, 16, additional, 13);

	total = (double)TC1_Get_us() - start;

	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	printk("AES-CCM  %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
}
#endif





#ifdef HAVE_CAMELLIA
void bench_camellia(void)
{
	Camellia cam;
	double start, total, persec;
	int    i;

	CamelliaSetKey(&cam, key, 16, iv);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	CamelliaCbcEncrypt(&cam, plain, cipher, sizeof(plain));

	total = (double)TC1_Get_us() - start;

	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	printk("Camellia %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
}
#endif





#ifndef NO_DES3
void bench_des(void)
{
	Des3   enc;
	double start, total, persec;
	int    i;

	#ifdef HAVE_CAVIUM
	if (Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0)
	printf("des3 init cavium failed\n");
	#endif
	Des3_SetKey(&enc, key, iv, DES_ENCRYPTION);
	start = (double)TC1_Get_us();

	for(i = 0; i < numBlocks; i++)
	Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain));

	total = (double)TC1_Get_us() - start;

	persec = 1 / total * numBlocks;
	#ifdef BENCH_EMBEDDED
	/* since using kB, convert to MB/s */
	persec = persec / 1024;
	#endif

	printk("3DES     %d %s took %d miliseconds\r\r\n", numBlocks,
	blockType, (int)total);
	#ifdef HAVE_CAVIUM
	Des3_FreeCavium(&enc);
	#endif
}
#endif








//
//double current_time(void)
//{
	//double rt = (double)tc_tick;
	//return rt;
//
//}
//
//

#endif